<commit_before>const { autoUpdater } = require('electron-updater')
const events = require('events')
const fetch = require('node-fetch')
const compareVersions = require('compare-versions')
const currentVersion = require('../../package.json').version

const networkSpeed = require('./network-speed')
const store = require('../store')
const logger = require('../logger')

// MapeoUpdater emits the 'error' event when there is an internal error with
// updating. We wrap electron-updater to control the API surface.
// Never use electron-updater directly in downstream modules.

const PERSISTED_STORE_KEY = 'updater.channel'
const VALID_CHANNELS = ['beta', 'latest', 'alpha']

class MapeoUpdater extends events.EventEmitter {
  constructor () {
    super()
    // Settings
    autoUpdater.channel = this.channel
    autoUpdater.autoDownload = false
    autoUpdater.logger = logger
    autoUpdater.autoInstallOnAppQuit = true
    autoUpdater.allowDowngrade = false
    this._onerror = this._onerror.bind(this)

    autoUpdater.on('error', this._onerror)
  }

  get channel () {
    let channel
    try {
      channel = store.get(PERSISTED_STORE_KEY)
    } catch (err) {
      // defaults to 'latest' when unset
      channel = autoUpdater.channel
    }
    if (channel !== autoUpdater.channel) autoUpdater.channel = channel
    return channel
  }

  set channel (value) {
    if (VALID_CHANNELS.indexOf(value) === -1) {
      logger.error('[UPDATER] Invalid channel', value)
      return
    }
    store.set(PERSISTED_STORE_KEY, value)
    autoUpdater.channel = value
    logger.info('[UPDATER] Channel updated to', updater.channel)
  }

  async _getReleaseSummary (version) {
    let releaseSummary
    try {
      const baseUrl = `https://downloads.mapeo.app/desktop/${version}/SUMMARY`
      releaseSummary = await fetch(baseUrl)
    } catch (err) {
      logger.error('[UPDATER] Error getting release notes', err)
      releaseSummary = null
    }
    return releaseSummary
  }

  async _getDownloadSpeed () {
    let downloadSpeed
    try {
      downloadSpeed = await networkSpeed.download()
      logger.info('[UPDATER] Got download speed', downloadSpeed)
    } catch (err) {
      logger.error('[UPDATER] Error getting download speed', err)
      downloadSpeed = null
    }
    return downloadSpeed
  }

  updateAvailable (onupdate) {
    autoUpdater.on('update-available', async ({
      version, files, path, sha512, releaseDate
    }) => {
      // this is a hack for a bug when you switch between channels,
      // it'll continue to say there is an update available when there is not
      // anymore
      if (compareVersions(version, currentVersion) <= 0) {
        return logger.info('Version', version, 'was less than curent version', currentVersion, 'ignoring update')
      }
      // TODO: Expose this in the UI somehow.
      if (!this.isActive()) {
        this.emit('update-inactive')
        return logger.info('[UPDATER] Must use an AppImage, dmg, or exe for automatic updates.')
      }

      var downloadSpeed = await this._getDownloadSpeed()

      var args = {
        version,
        files,
        path,
        sha512,
        releaseDate,
        downloadSpeed,
        releaseSummary: null // TODO: this._getReleaseSummary(version)
      }

      onupdate(args)
    })
  }

  updateNotAvailable (cb) {
    autoUpdater.on('update-not-available', cb)
  }

  downloadProgress (onprogress) {
    autoUpdater.on('download-progress', (progress) => {
      logger.info('[UPDATER] Progress', progress)
      onprogress({
        progress: progress
      })
    })
  }

  updateDownloaded (cb) {
    autoUpdater.on('update-downloaded', cb)
  }

  periodicUpdates (interval) {
    const FOUR_HOURS = 1000 * 60 * 60 * 4
    setInterval(async () => {
      this.checkForUpdates()
    }, interval || FOUR_HOURS)
    this.checkForUpdates()
  }

  downloadUpdate () {
    if (!this.isActive()) return Promise.reject(new Error('Cannot download.'))
    logger.info('[UPDATER] Download initiated.')
    var promise = autoUpdater.downloadUpdate()

    promise
      .then(() => logger.error('[UPDATER] Download successful.'))
      .catch(this._onerror)
    return promise
  }

  isActive () {
    return autoUpdater.isUpdaterActive()
  }

  checkForUpdates (cb) {
    if (!cb) cb = () => {}
    try {
      var promise = autoUpdater.checkForUpdates()
      promise
        .then(update => cb(null, update))
        .catch(this._onerror)
    } catch (err) {
      // TODO: error codes for internationalization.
      var error = new Error('[UPDATER] Could not check for updates.', err)
      this._onerror(error)
    }
  }

  _onerror (err) {
    logger.error('[UPDATER]', err)
    this.emit('error', err)
  }

  quitAndInstall () {
    autoUpdater.quitAndInstall()
  }
}

var updater
if (!updater) updater = new MapeoUpdater()

module.exports = updater
<commit_msg>fix: Properly return error when updater is inactive<commit_after>const { autoUpdater } = require('electron-updater')
const events = require('events')
const fetch = require('node-fetch')
const compareVersions = require('compare-versions')
const currentVersion = require('../../package.json').version

const networkSpeed = require('./network-speed')
const store = require('../store')
const logger = require('../logger')

// MapeoUpdater emits the 'error' event when there is an internal error with
// updating. We wrap electron-updater to control the API surface.
// Never use electron-updater directly in downstream modules.

const PERSISTED_STORE_KEY = 'updater.channel'
const VALID_CHANNELS = ['beta', 'latest', 'alpha']

class MapeoUpdater extends events.EventEmitter {
  constructor () {
    super()
    // Settings
    autoUpdater.channel = this.channel
    autoUpdater.autoDownload = false
    autoUpdater.logger = logger
    autoUpdater.autoInstallOnAppQuit = true
    autoUpdater.allowDowngrade = false
    this._onerror = this._onerror.bind(this)

    autoUpdater.on('error', this._onerror)
  }

  get channel () {
    let channel
    try {
      channel = store.get(PERSISTED_STORE_KEY)
    } catch (err) {
      // defaults to 'latest' when unset
      channel = autoUpdater.channel
    }
    if (channel !== autoUpdater.channel) autoUpdater.channel = channel
    return channel
  }

  set channel (value) {
    if (VALID_CHANNELS.indexOf(value) === -1) {
      logger.error('[UPDATER] Invalid channel', value)
      return
    }
    store.set(PERSISTED_STORE_KEY, value)
    autoUpdater.channel = value
    logger.info('[UPDATER] Channel updated to', updater.channel)
  }

  async _getReleaseSummary (version) {
    let releaseSummary
    try {
      const baseUrl = `https://downloads.mapeo.app/desktop/${version}/SUMMARY`
      releaseSummary = await fetch(baseUrl)
    } catch (err) {
      logger.error('[UPDATER] Error getting release notes', err)
      releaseSummary = null
    }
    return releaseSummary
  }

  async _getDownloadSpeed () {
    let downloadSpeed
    try {
      downloadSpeed = await networkSpeed.download()
      logger.info('[UPDATER] Got download speed', downloadSpeed)
    } catch (err) {
      logger.error('[UPDATER] Error getting download speed', err)
      downloadSpeed = null
    }
    return downloadSpeed
  }

  updateAvailable (onupdate) {
    autoUpdater.on('update-available', async ({
      version, files, path, sha512, releaseDate
    }) => {
      // this is a hack for a bug when you switch between channels,
      // it'll continue to say there is an update available when there is not
      // anymore
      if (compareVersions(version, currentVersion) <= 0) {
        return logger.info('Version', version, 'was less than curent version', currentVersion, 'ignoring update')
      }
      // TODO: Expose this in the UI somehow.
      if (!this.isActive()) {
        this.emit('update-inactive')
        return logger.info('[UPDATER] Must use an AppImage, dmg, or exe for automatic updates.')
      }

      var downloadSpeed = await this._getDownloadSpeed()

      var args = {
        version,
        files,
        path,
        sha512,
        releaseDate,
        downloadSpeed,
        releaseSummary: null // TODO: this._getReleaseSummary(version)
      }

      onupdate(args)
    })
  }

  updateNotAvailable (cb) {
    autoUpdater.on('update-not-available', cb)
  }

  downloadProgress (onprogress) {
    autoUpdater.on('download-progress', (progress) => {
      logger.info('[UPDATER] Progress', progress)
      onprogress({
        progress: progress
      })
    })
  }

  updateDownloaded (cb) {
    autoUpdater.on('update-downloaded', cb)
  }

  periodicUpdates (interval) {
    const FOUR_HOURS = 1000 * 60 * 60 * 4
    setInterval(async () => {
      this.checkForUpdates()
    }, interval || FOUR_HOURS)
    this.checkForUpdates()
  }

  downloadUpdate () {
    if (!this.isActive()) return this._onerror(new Error('Cannot download.'))
    logger.info('[UPDATER] Download initiated.')
    var promise = autoUpdater.downloadUpdate()

    promise
      .then(() => logger.error('[UPDATER] Download successful.'))
      .catch(this._onerror)
    return promise
  }

  isActive () {
    return autoUpdater.isUpdaterActive()
  }

  checkForUpdates (cb) {
    if (!cb) cb = () => {}
    try {
      var promise = autoUpdater.checkForUpdates()
      promise
        .then(update => cb(null, update))
        .catch(this._onerror)
    } catch (err) {
      // TODO: error codes for internationalization.
      var error = new Error('[UPDATER] Could not check for updates.', err)
      this._onerror(error)
    }
  }

  _onerror (err) {
    logger.error('[UPDATER]', err)
    this.emit('error', err)
  }

  quitAndInstall () {
    autoUpdater.quitAndInstall()
  }
}

var updater
if (!updater) updater = new MapeoUpdater()

module.exports = updater
<|endoftext|>


<commit_before>;

import angular from 'angular';
import squareImageModule from '../components/square-image';
import { labels } from '../won-label-utils';
import {attach} from '../utils.js';
import { actionCreators }  from '../actions/actions';

const serviceDependencies = ['$q', '$ngRedux', '$scope'];
function genComponentConf() {
    let template = `

                <won-square-image src="self.item.titleImgSrc" title="self.item[0].ownNeed.title"></won-square-image>

{{self.item[0].ownNeed.title}}

{{self.item.length}}

                            {{self.item.group}} –

                        {{self.wonLabels.type[self.item[0].ownNeed.basicNeedType]}}

                    <won-square-image src="request.titleImgSrc" title="request.remoteNeed.title"></won-square-image>

{{request.remoteNeed.title}}

{{request.timeStamp}}

                                {{request.group}} –

                            {{self.wonLabels.type[self.item[0].remoteNeed.basicNeedType]}}

                            {{request.message}}

    `;

    class Controller {
        constructor() {
            attach(this, serviceDependencies, arguments);
            console.log(this.item)
            window.reqitemline = this;
            const selectFromState = (state)=>{

                return {
                    unreadUris: state.getIn(['events','unreadEventUris'])
                };
            }
            console.log(this.item);
            this.wonLabels = labels;

            const disconnect = this.$ngRedux.connect(selectFromState,actionCreators)(this);
            //  this.loadMatches();
            this.$scope.$on('$destroy', disconnect);
        }

        read(request){
            if(!this.unreadUris.has(request.connection.uri)){
                return true
            }
            return false;
        }
        toggleRequest() {
            this.open = !this.open;
        }

        openMessage(request) {
            this.events__read(request.connection.uri)
            this.openRequest = request;
        }

    }
    Controller.$inject = serviceDependencies;
    return {
        restrict: 'E',
        controller: Controller,
        controllerAs: 'self',
        bindToController: true, //scope-bindings -> ctrl
        scope: {item: "=",
                open: "=",
                openRequest: "="},
        template: template
    }

}

export default angular.module('won.owner.components.requestItemLine', [])
    .directive('wonRequestItemLine', genComponentConf)
    .name;

<commit_msg>Plz remove dbg output before merging with devel.<commit_after>;

import angular from 'angular';
import squareImageModule from '../components/square-image';
import { labels } from '../won-label-utils';
import {attach} from '../utils.js';
import { actionCreators }  from '../actions/actions';

const serviceDependencies = ['$q', '$ngRedux', '$scope'];
function genComponentConf() {
    let template = `

                <won-square-image src="self.item.titleImgSrc" title="self.item[0].ownNeed.title"></won-square-image>

{{self.item[0].ownNeed.title}}

{{self.item.length}}

                            {{self.item.group}} –

                        {{self.wonLabels.type[self.item[0].ownNeed.basicNeedType]}}

                    <won-square-image src="request.titleImgSrc" title="request.remoteNeed.title"></won-square-image>

{{request.remoteNeed.title}}

{{request.timeStamp}}

                                {{request.group}} –

                            {{self.wonLabels.type[self.item[0].remoteNeed.basicNeedType]}}

                            {{request.message}}

    `;

    class Controller {
        constructor() {
            attach(this, serviceDependencies, arguments);
            window.reqitemline = this;
            const selectFromState = (state)=>{

                return {
                    unreadUris: state.getIn(['events','unreadEventUris'])
                };
            }
            this.wonLabels = labels;

            const disconnect = this.$ngRedux.connect(selectFromState,actionCreators)(this);
            //  this.loadMatches();
            this.$scope.$on('$destroy', disconnect);
        }

        read(request){
            if(!this.unreadUris.has(request.connection.uri)){
                return true
            }
            return false;
        }
        toggleRequest() {
            this.open = !this.open;
        }

        openMessage(request) {
            this.events__read(request.connection.uri)
            this.openRequest = request;
        }

    }
    Controller.$inject = serviceDependencies;
    return {
        restrict: 'E',
        controller: Controller,
        controllerAs: 'self',
        bindToController: true, //scope-bindings -> ctrl
        scope: {item: "=",
                open: "=",
                openRequest: "="},
        template: template
    }

}

export default angular.module('won.owner.components.requestItemLine', [])
    .directive('wonRequestItemLine', genComponentConf)
    .name;

<|endoftext|>


<commit_before>const configurator = require("@nteract/webpack-configurator");
const LodashModuleReplacementPlugin = require("lodash-webpack-plugin");
const webpack = require("webpack");
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");

const nodeEnv = process.env.NODE_ENV || "development";
const isProd = nodeEnv === "production";

const plugins = [
  new MonacoWebpackPlugin(),
  new webpack.IgnorePlugin(
    /^((fs)|(path)|(os)|(crypto)|(source-map-support))$/,
    /vs\/language\/typescript\/lib/
  )
];

if (isProd) {
  plugins.push(new LodashModuleReplacementPlugin());
} else {
  plugins.push(new webpack.HotModuleReplacementPlugin());
}

module.exports = {
  externals: ["canvas"],
  mode: isProd ? "production" : "development",
  devtool: isProd ? "hidden-source-map" : "cheap-eval-source-map",
  entry: {
    app: "./app/index.tsx"
  },
  devServer: isProd
    ? {}
    : {
        publicPath: "/nteract/static/dist/",
        hot: true,
        headers: { "Access-Control-Allow-Origin": "*" }
      },
  target: "web",
  output: {
    chunkFilename: "[name]-[chunkhash].bundle.js"
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      },
      {
        test: /\.tsx?$/,
        use: [
          {
            loader: "ts-loader",
            options: {
              transpileOnly: true,
              compilerOptions: {
                noEmit: false
              }
            }
          }
        ]
      }
    ]
  },
  resolve: {
    mainFields: ["nteractDesktop", "module", "main"],
    extensions: [".ts", ".tsx", ".js"],
    alias: configurator.mergeDefaultAliases()
  },
  plugins
};
<commit_msg>dont use chunkhash in name when in dev<commit_after>const configurator = require("@nteract/webpack-configurator");
const LodashModuleReplacementPlugin = require("lodash-webpack-plugin");
const webpack = require("webpack");
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");

const nodeEnv = process.env.NODE_ENV || "development";
const isProd = nodeEnv === "production";

const plugins = [
  new MonacoWebpackPlugin(),
  new webpack.IgnorePlugin(
    /^((fs)|(path)|(os)|(crypto)|(source-map-support))$/,
    /vs\/language\/typescript\/lib/
  )
];

if (isProd) {
  plugins.push(new LodashModuleReplacementPlugin());
} else {
  plugins.push(new webpack.HotModuleReplacementPlugin());
}

module.exports = {
  externals: ["canvas"],
  mode: isProd ? "production" : "development",
  devtool: isProd ? "hidden-source-map" : "cheap-eval-source-map",
  entry: {
    app: "./app/index.tsx"
  },
  devServer: isProd
    ? {}
    : {
        publicPath: "/nteract/static/dist/",
        hot: true,
        headers: { "Access-Control-Allow-Origin": "*" }
      },
  target: "web",
  output: {
    chunkFilename: isProd ? "[name]-[chunkhash].bundle.js" : "[name].bundle.js"
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      },
      {
        test: /\.tsx?$/,
        use: [
          {
            loader: "ts-loader",
            options: {
              transpileOnly: true,
              compilerOptions: {
                noEmit: false
              }
            }
          }
        ]
      }
    ]
  },
  resolve: {
    mainFields: ["nteractDesktop", "module", "main"],
    extensions: [".ts", ".tsx", ".js"],
    alias: configurator.mergeDefaultAliases()
  },
  plugins
};
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
({
    displayValue: function(component) {
        var value = component.get("v.value");
        var displayValue = value;
        if (value) {
            var d = $A.localizationService.parseDateTimeUTC(value, "yyyy-MM-dd");
            if (d) {
                var format = component.get("v.format");
                var langLocale = component.get("v.langLocale");
                try {
                    d = $A.localizationService.translateToOtherCalendar(d);
                    displayValue = $A.localizationService.formatDateUTC(d, format, langLocale);
                } catch (e) {
                    displayValue = e.message;
                }
            }
        }
        var elem = component.find("inputText").getElement();
        elem.value = displayValue ? $A.localizationService.translateToLocalizedDigits(displayValue) : '';
    },

    displayDatePicker: function(component) {
        var datePicker = component.find("datePicker");
        if (datePicker && datePicker.get("v.visible") === false) {
            var currentDate = new Date();
            var value = component.get("v.value");
            if (value) {
                currentDate = $A.localizationService.parseDateTime(value, "yyyy-MM-dd");
            }
            datePicker.set("v.value", this.getDateString(currentDate));
            datePicker.set("v.visible", true);
        }
    },

    /**
     * Override ui:input.
     *
     */
    doUpdate : function(component, value) {
        var v = $A.localizationService.translateFromLocalizedDigits(value);
        var ret = v;
        if (value) {
            var format = component.get("v.format");
            if (!format) { // use default format
                format = $A.get("$Locale.dateformat");
            }
            var langLocale = component.get("v.langLocale");
            var d = $A.localizationService.parseDateTimeUTC(v, format, langLocale);
            if (d) {
                d = $A.localizationService.translateFromOtherCalendar(d);
                ret = $A.localizationService.formatDateUTC(d, "YYYY-MM-DD");
            }
        }
        component.set("v.value", ret);
    },

    getDateString: function(date) {
        return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
    }
})<commit_msg>Modifying inputDateHelper so that inputDate can be extended @rec dmcmillen@ @bug w-2190470@<commit_after>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
({
    displayValue: function(component) {
	var concCmp = component.getConcreteComponent();
        var value = concCmp.get("v.value");
        var displayValue = value;
        if (value) {
            var d = $A.localizationService.parseDateTimeUTC(value, "yyyy-MM-dd");
            if (d) {
                var format = concCmp.get("v.format");
                var langLocale = concCmp.get("v.langLocale");
                try {
                    d = $A.localizationService.translateToOtherCalendar(d);
                    displayValue = $A.localizationService.formatDateUTC(d, format, langLocale);
                } catch (e) {
                    displayValue = e.message;
                }
            }
        }
        var elem = concCmp.find("inputText").getElement();
        elem.value = displayValue ? $A.localizationService.translateToLocalizedDigits(displayValue) : '';
    },

    displayDatePicker: function(component) {
	var concCmp = component.getConcreteComponent();
        var datePicker = concCmp.find("datePicker");
        if (datePicker && datePicker.get("v.visible") === false) {
            var currentDate = new Date();
            var value = concCmp.get("v.value");
            if (value) {
                currentDate = $A.localizationService.parseDateTime(value, "yyyy-MM-dd");
            }
            datePicker.set("v.value", this.getDateString(currentDate));
            datePicker.set("v.visible", true);
        }
    },

    /**
     * Override ui:input.
     *
     */
    doUpdate : function(component, value) {
	var concCmp = component.getConcreteComponent();
        var v = $A.localizationService.translateFromLocalizedDigits(value);
        var ret = v;
        if (value) {
            var format = concCmp.get("v.format");
            if (!format) { // use default format
                format = $A.get("$Locale.dateformat");
            }
            var langLocale = concCmp.get("v.langLocale");
            var d = $A.localizationService.parseDateTimeUTC(v, format, langLocale);
            if (d) {
                d = $A.localizationService.translateFromOtherCalendar(d);
                ret = $A.localizationService.formatDateUTC(d, "YYYY-MM-DD");
            }
        }
        concCmp.set("v.value", ret);
    },

    getDateString: function(date) {
        return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
    }
})<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function lib() { // eslint-disable-line no-unused-vars

    var abbreviations = {
        thousand : 'k',
        million  : 'm',
        billion  : 'b',
        trillion : 't'
    };

    function getMaxFractionDigits (pattern, symbols) {
        var decimalSeparator = symbols && symbols.decimalSeparator ? symbols.decimalSeparator : '.';
        var zero = symbols && symbols.zero ? symbols.zero : '0';
        var patternSplit = pattern.split(decimalSeparator);
        var reg = new RegExp('[^(#'+ zero + ']','g');
        if (patternSplit.length > 1) {
            return patternSplit[1].replace(reg,'').length;
        }
        return 0;
    }

    return {
        formatNumber: function (number, formatter) {
            var numberFormat = this.getNumberFormat(formatter);

            if (!$A.util.isUndefinedOrNull(number) && !isNaN(number)) {
                return numberFormat.format(number);
            }
            return '';
        },
        getNumberFormat: function (formatter) {
            if (typeof formatter === 'string') {
                try {
                    return $A.localizationService.getNumberFormat(formatter);
                } catch (e) {
                    // invalid number format error
                    // use default instead and show a warning on console
                    return $A.localizationService.getDefaultNumberFormat();
                }
            }
            return $A.localizationService.getDefaultNumberFormat();
        },
        unFormatNumber: function (string ) {
            var decimalSeparator = $A.get("$Locale.decimal");
            var currencySymbol   = $A.get("$Locale.currency");

            var stringOriginal = string,
                thousandRegExp,
                millionRegExp,
                billionRegExp,
                trillionRegExp;

            if (this.isNumber(string)) {
                return string;
            }

            if (decimalSeparator !== '.') {
                string = string.replace(/\./g, '').replace(decimalSeparator, '.');
            }

            // see if abbreviations are there so that we can multiply to the correct number
            thousandRegExp = new RegExp('[^a-zA-Z]' + abbreviations.thousand + '(?:\\)|(\\' + currencySymbol + ')?(?:\\))?)?$', 'i');
            millionRegExp  = new RegExp('[^a-zA-Z]' + abbreviations.million  + '(?:\\)|(\\' + currencySymbol + ')?(?:\\))?)?$', 'i');
            billionRegExp  = new RegExp('[^a-zA-Z]' + abbreviations.billion  + '(?:\\)|(\\' + currencySymbol + ')?(?:\\))?)?$', 'i');
            trillionRegExp = new RegExp('[^a-zA-Z]' + abbreviations.trillion + '(?:\\)|(\\' + currencySymbol + ')?(?:\\))?)?$', 'i');
            // do some math to create our number
            return ((stringOriginal.match(thousandRegExp)) ? Math.pow(10, 3) : 1) *
                   ((stringOriginal.match(millionRegExp))  ? Math.pow(10, 6) : 1) *
                   ((stringOriginal.match(billionRegExp))  ? Math.pow(10, 9) : 1) *
                   ((stringOriginal.match(trillionRegExp)) ? Math.pow(10, 12) : 1) *
                   ((string.indexOf('%') > -1) ? 0.01 : 1) *
                   (((string.split('-').length + Math.min(string.split('(').length - 1, string.split(')').length - 1)) % 2) ? 1 : -1) *
                   Number(string.replace(/[^0-9\.]+/g, ''));
        },
        isNumber: function (number) {
            return $A.util.isNumber(number);
        },
        isFormattedNumber: function (string, formatter) {
            var zero              = $A.get("$Locale.zero");
            var decimalSeparator  = $A.get("$Locale.decimal");
            var groupingSeparator = $A.get("$Locale.grouping");
            var maxFractionDigits = getMaxFractionDigits(formatter, { decimalSeparator : decimalSeparator, zero : zero});

            var const1 = '(?!(K|B|M|T|\\' + decimalSeparator + '))';

            // This regexp math with any formatted number or any possible formatted number
            // Match with :
            // never start with letter(k,b,m,t,(decimalSeparator))
            // everything that start with ( space* (+|-) spaces* )
            // any repeat of #{1}(groupingSeparator)#{0,n}
            // follow decimalSeparator #{0,maxFractionDigits} (not required)
            // ended by any shortcut (K|B|M|T)
            // it not case sensitive
            var regString = '^' + const1 + '((\\s*(\\+|\\-)?\\s*)' + const1 + ')?' +
                            '(\\d+(\\' + groupingSeparator + '\\d*)*)*' +
                            '(\\' + decimalSeparator + '\\d{0,' + maxFractionDigits + '})?' +
                            '(K|B|M|T)?$';

            var reg = new RegExp(regString, 'i');
            return reg.test(string);
        }
    };
}

<commit_msg>fix percent unformat issue @bug W-2961636@ @rev stephen.woods@<commit_after>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function lib() { // eslint-disable-line no-unused-vars

    var abbreviations = {
        thousand : 'k',
        million  : 'm',
        billion  : 'b',
        trillion : 't'
    };

    function getMaxFractionDigits (pattern, symbols) {
        var decimalSeparator = symbols && symbols.decimalSeparator ? symbols.decimalSeparator : '.';
        var zero = symbols && symbols.zero ? symbols.zero : '0';
        var patternSplit = pattern.split(decimalSeparator);
        var reg = new RegExp('[^(#'+ zero + ']','g');
        if (patternSplit.length > 1) {
            return patternSplit[1].replace(reg,'').length;
        }
        return 0;
    }

    return {
        formatNumber: function (number, formatter) {
            var numberFormat = this.getNumberFormat(formatter);

            if (!$A.util.isUndefinedOrNull(number) && !isNaN(number)) {
                return numberFormat.format(number);
            }
            return '';
        },
        getNumberFormat: function (formatter) {
            if (typeof formatter === 'string') {
                try {
                    return $A.localizationService.getNumberFormat(formatter);
                } catch (e) {
                    // invalid number format error
                    // use default instead and show a warning on console
                    return $A.localizationService.getDefaultNumberFormat();
                }
            }
            return $A.localizationService.getDefaultNumberFormat();
        },
        unFormatNumber: function (string ) {
            var decimalSeparator = $A.get("$Locale.decimal");
            var currencySymbol   = $A.get("$Locale.currency");

            var stringOriginal = string,
                thousandRegExp,
                millionRegExp,
                billionRegExp,
                trillionRegExp;

            if (this.isNumber(string)) {
                return string;
            }

            if (decimalSeparator !== '.') {
                string = string.replace(/\./g, '').replace(decimalSeparator, '.');
            }

            // see if abbreviations are there so that we can multiply to the correct number
            thousandRegExp = new RegExp('[^a-zA-Z]' + abbreviations.thousand + '(?:\\)|(\\' + currencySymbol + ')?(?:\\))?)?$', 'i');
            millionRegExp  = new RegExp('[^a-zA-Z]' + abbreviations.million  + '(?:\\)|(\\' + currencySymbol + ')?(?:\\))?)?$', 'i');
            billionRegExp  = new RegExp('[^a-zA-Z]' + abbreviations.billion  + '(?:\\)|(\\' + currencySymbol + ')?(?:\\))?)?$', 'i');
            trillionRegExp = new RegExp('[^a-zA-Z]' + abbreviations.trillion + '(?:\\)|(\\' + currencySymbol + ')?(?:\\))?)?$', 'i');
            // do some math to create our number
            return ((stringOriginal.match(thousandRegExp)) ? Math.pow(10, 3) : 1) *
                   ((stringOriginal.match(millionRegExp))  ? Math.pow(10, 6) : 1) *
                   ((stringOriginal.match(billionRegExp))  ? Math.pow(10, 9) : 1) *
                   ((stringOriginal.match(trillionRegExp)) ? Math.pow(10, 12) : 1) *
                   (((string.split('-').length + Math.min(string.split('(').length - 1, string.split(')').length - 1)) % 2) ? 1 : -1) *
                   Number(string.replace(/[^0-9\.]+/g, ''));
        },
        isNumber: function (number) {
            return $A.util.isNumber(number);
        },
        isFormattedNumber: function (string, formatter) {
            var zero              = $A.get("$Locale.zero");
            var decimalSeparator  = $A.get("$Locale.decimal");
            var groupingSeparator = $A.get("$Locale.grouping");
            var maxFractionDigits = getMaxFractionDigits(formatter, { decimalSeparator : decimalSeparator, zero : zero});

            var const1 = '(?!(K|B|M|T|\\' + decimalSeparator + '))';

            // This regexp math with any formatted number or any possible formatted number
            // Match with :
            // never start with letter(k,b,m,t,(decimalSeparator))
            // everything that start with ( space* (+|-) spaces* )
            // any repeat of #{1}(groupingSeparator)#{0,n}
            // follow decimalSeparator #{0,maxFractionDigits} (not required)
            // ended by any shortcut (K|B|M|T)
            // it not case sensitive
            var regString = '^' + const1 + '((\\s*(\\+|\\-)?\\s*)' + const1 + ')?' +
                            '(\\d+(\\' + groupingSeparator + '\\d*)*)*' +
                            '(\\' + decimalSeparator + '\\d{0,' + maxFractionDigits + '})?' +
                            '(K|B|M|T)?$';

            var reg = new RegExp(regString, 'i');
            return reg.test(string);
        }
    };
}

<|endoftext|>


<commit_before>var e = module.exports = {};

e.init = () => {
    e.category = bu.CommandType.CAT;
};

e.requireCtx = require;

e.isCommand = true;

e.hidden = false;
e.usage = 'module <reload|unload|load> <name>';
e.info = 'Loads, unloads, or reloads a module';

e.flags = [{
    flag: 'c',
    word: 'command',
    desc: 'Do for a command (default)'
}, {
    flag: 't',
    word: 'tag',
    desc: 'Do for a tag'
}, {
    flag: 'e',
    word: 'event',
    desc: 'Do for an event'
}];

var confirmIrc = false;
var confirmDiscord = false;
e.execute = (msg, words) => {
    if (msg.author.id == bu.CAT_ID) {
        let input = bu.parseInput(e.flags, words);
        let manager = CommandManager;
        if (input.e) manager = EventManager;
        if (input.t) manager = TagManager;
        if (input.c) manager = CommandManager;

        if (words.length > 1) {
            switch (words.shift().toLowerCase()) {
                case 'reload':
                    if (manager.reload(words[0]))
                        bu.send(msg, `:ok_hand: Reloaded ${manager.type} ${words[0]} :ok_hand:`);
                    else bu.send(msg, `:no_good: Failed to reload ${manager.type} ${words[0]} :no_good:`);
                    break;
                case 'unload':
                    if (manager.unload(words[0]))
                        bu.send(msg, `:ok_hand: Unloaded ${manager.type} ${words[0]} :ok_hand:`);
                    else bu.send(msg, `:no_good: Failed to unload ${manager.type} ${words[0]} :no_good:`);
                    break;
                case 'load':
                    if (manager.load(words[0]))
                        bu.send(msg, `:ok_hand: Loaded ${manager.type} ${words[0]} :ok_hand:`);
                    else bu.send(msg, `:no_good: Failed to load ${manager.type} ${words[0]} :no_good:`);
                    break;
            }
        } else {
            if (words[0] && words[0].toLowerCase() == 'discord') {
                if (!confirmDiscord) {
                    bu.send(msg, 'I really hope you know what you\'re doing. ' +
                        'Type that command again to confirm.');
                    confirmDiscord = true;
                } else {
                    bu.send(msg, `:ok_hand: Reloading the discord module :ok_hand:`)
                        .then(() => {
                            bu.emitter.emit('reloadDiscord');
                        });
                }
            } else if (words[0] && words[0].toLowerCase() == 'irc') {
                if (!confirmIrc) {
                    bu.send(msg, `I really hope you know what you're doing. ` +
                        `Type that command again to confirm.`);
                    confirmIrc = true;
                } else {
                    bu.send(msg, `:ok_hand: Reloading the irc module :ok_hand:`)
                        .then(() => {
                            bu.emitter.emit('reloadIrc');
                        });
                }
            } else if (words[0] && words[0].toLowerCase() == 'bu') {
                bu.emitter.emit('reloadBu');
            } else if (words[0] && words[0].toLowerCase() == 'cluster') {
                cluster.reset();
                bu.send(msg, `:ok_hand: Reloading the workers. :ok_hand:`);
            }
        }
    }
};<commit_msg>add support for tags and events<commit_after>var e = module.exports = {};

e.init = () => {
    e.category = bu.CommandType.CAT;
};

e.requireCtx = require;

e.isCommand = true;

e.hidden = false;
e.usage = 'module <reload|unload|load> <name>';
e.info = 'Loads, unloads, or reloads a module';

e.flags = [{
    flag: 'c',
    word: 'command',
    desc: 'Do for a command (default)'
}, {
    flag: 't',
    word: 'tag',
    desc: 'Do for a tag'
}, {
    flag: 'e',
    word: 'event',
    desc: 'Do for an event'
}];

var confirmIrc = false;
var confirmDiscord = false;
e.execute = (msg, words) => {
    if (msg.author.id == bu.CAT_ID) {
        let input = bu.parseInput(e.flags, words);
        if (input.undefined.length > 1) {
            let manager = CommandManager;
            if (input.e) manager = EventManager;
            if (input.t) manager = TagManager;
            if (input.c) manager = CommandManager;
            switch (input.undefined.shift().toLowerCase()) {
                case 'reload':
                    if (manager.reload(input.undefined[0]))
                        bu.send(msg, `:ok_hand: Reloaded ${manager.type} ${input.undefined[0]} :ok_hand:`);
                    else bu.send(msg, `:no_good: Failed to reload ${manager.type} ${input.undefined[0]} :no_good:`);
                    break;
                case 'unload':
                    if (manager.unload(input.undefined[0]))
                        bu.send(msg, `:ok_hand: Unloaded ${manager.type} ${input.undefined[0]} :ok_hand:`);
                    else bu.send(msg, `:no_good: Failed to unload ${manager.type} ${input.undefined[0]} :no_good:`);
                    break;
                case 'load':
                    if (manager.load(input.undefined[0]))
                        bu.send(msg, `:ok_hand: Loaded ${manager.type} ${input.undefined[0]} :ok_hand:`);
                    else bu.send(msg, `:no_good: Failed to load ${manager.type} ${input.undefined[0]} :no_good:`);
                    break;
            }
        } else {
            if (input.undefined[0] && input.undefined[0].toLowerCase() == 'discord') {
                if (!confirmDiscord) {
                    bu.send(msg, 'I really hope you know what you\'re doing. ' +
                        'Type that command again to confirm.');
                    confirmDiscord = true;
                } else {
                    bu.send(msg, `:ok_hand: Reloading the discord module :ok_hand:`)
                        .then(() => {
                            bu.emitter.emit('reloadDiscord');
                        });
                }
            } else if (input.undefined[0] && input.undefined[0].toLowerCase() == 'irc') {
                if (!confirmIrc) {
                    bu.send(msg, `I really hope you know what you're doing. ` +
                        `Type that command again to confirm.`);
                    confirmIrc = true;
                } else {
                    bu.send(msg, `:ok_hand: Reloading the irc module :ok_hand:`)
                        .then(() => {
                            bu.emitter.emit('reloadIrc');
                        });
                }
            } else if (input.undefined[0] && input.undefined[0].toLowerCase() == 'bu') {
                bu.emitter.emit('reloadBu');
            } else if (input.undefined[0] && input.undefined[0].toLowerCase() == 'cluster') {
                cluster.reset();
                bu.send(msg, `:ok_hand: Reloading the workers. :ok_hand:`);
            }
        }
    }
};<|endoftext|>


<commit_before>/*global module:true*/
(function(){
  var table = function(converter) {
    var tables = {}, style = 'text-align:left;', filter;
    tables.th = function(header){
      if (header.trim() === "") { return "";}
      var id = header.trim().replace(/ /g, '_').toLowerCase();
      return '' + header + '	';
    };
    tables.td = function(cell) {
      return '' + cell + '	';
    };
    tables.ths = function(){
      var out = "", i = 0, hs = [].slice.apply(arguments);
      for (i;i<hs.length;i+=1) {
        out += tables.th(hs[i]) + '\n';
      }
      return out;
    };
    tables.tds = function(){
      var out = "", i = 0, ds = [].slice.apply(arguments);
      for (i;i<ds.length;i+=1) {
        out += tables.td(ds[i]) + '\n';
      }
      return out;
    };
    tables.thead = function() {
      var out, i = 0, hs = [].slice.apply(arguments);
      out = "
\n";
      out += "
\n";
      out += tables.ths.apply(this, hs);
      out += "
\n";
      out += "
\n";
      return out;
    };
    tables.tr = function() {
      var out, i = 0, cs = [].slice.apply(arguments);
      out = "
\n";
      out += tables.tds.apply(this, cs);
      out += "
\n";
      return out;
    };
    filter = function(text) {
      var i=0, lines = text.split('\n'), tbl = [], line, hs, rows, out = [];
      for (i; i<lines.length;i+=1) {
        line = lines[i];
        // looks like a table heading
        if (line.trim().match(/^[|]{1}.*[|]{1}$/)) {
          line = line.trim();
          tbl.push('
');
          hs = line.substring(1, line.length -1).split('|');
          tbl.push(tables.thead.apply(this, hs));
          line = lines[++i];
          if (!line.trim().match(/^[|]{1}[-=| ]+[|]{1}$/)) {
            // not a table rolling back
            line = lines[--i];
          }
          else {
            line = lines[++i];
            tbl.push('
');
            while (line.trim().match(/^[|]{1}.*[|]{1}$/)) {
              line = line.trim();
              tbl.push(tables.tr.apply(this, line.substring(1, line.length -1).split('|')));
              line = lines[++i];
            }
            tbl.push('
');
            tbl.push('
');
            // we are done with this table and we move along
            out.push(tbl.join('\n'));
            ++i;
            continue;
          }
        }
        out.push(line);
      }
      return out.join('\n');
    };
    return [
    {
      type: 'lang',
      filter: filter
    }
    ];
  };

  // Client-side export
  if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.table = table; }
  // Server-side export
  if (typeof module !== 'undefined') {
    module.exports = table;
  }
}());
<commit_msg>add re-entering support for table content<commit_after>/*global module:true*/
/*
 * Basic table support with re-entrant parsing, where cell content
 * can also specify markdown.
 *
 * Tables
 * ======
 *
 * | Col 1   | Col 2                                              |
 * |======== |====================================================|
 * |**bold** | ![Valid XHTML] (http://w3.org/Icons/valid-xhtml10) |
 * | Plain   | Value                                              |
 *
 */

(function(){
  var table = function(converter) {
    var tables = {}, style = 'text-align:left;', filter;
    tables.th = function(header){
      if (header.trim() === "") { return "";}
      var id = header.trim().replace(/ /g, '_').toLowerCase();
      return '' + header + '	';
    };
    tables.td = function(cell) {
      return '' + converter.makeHtml(cell) + '	';
    };
    tables.ths = function(){
      var out = "", i = 0, hs = [].slice.apply(arguments);
      for (i;i<hs.length;i+=1) {
        out += tables.th(hs[i]) + '\n';
      }
      return out;
    };
    tables.tds = function(){
      var out = "", i = 0, ds = [].slice.apply(arguments);
      for (i;i<ds.length;i+=1) {
        out += tables.td(ds[i]) + '\n';
      }
      return out;
    };
    tables.thead = function() {
      var out, i = 0, hs = [].slice.apply(arguments);
      out = "
\n";
      out += "
\n";
      out += tables.ths.apply(this, hs);
      out += "
\n";
      out += "
\n";
      return out;
    };
    tables.tr = function() {
      var out, i = 0, cs = [].slice.apply(arguments);
      out = "
\n";
      out += tables.tds.apply(this, cs);
      out += "
\n";
      return out;
    };
    filter = function(text) {
      var i=0, lines = text.split('\n'), tbl = [], line, hs, rows, out = [];
      for (i; i<lines.length;i+=1) {
        line = lines[i];
        // looks like a table heading
        if (line.trim().match(/^[|]{1}.*[|]{1}$/)) {
          line = line.trim();
          tbl.push('
');
          hs = line.substring(1, line.length -1).split('|');
          tbl.push(tables.thead.apply(this, hs));
          line = lines[++i];
          if (!line.trim().match(/^[|]{1}[-=| ]+[|]{1}$/)) {
            // not a table rolling back
            line = lines[--i];
          }
          else {
            line = lines[++i];
            tbl.push('
');
            while (line.trim().match(/^[|]{1}.*[|]{1}$/)) {
              line = line.trim();
              tbl.push(tables.tr.apply(this, line.substring(1, line.length -1).split('|')));
              line = lines[++i];
            }
            tbl.push('
');
            tbl.push('
');
            // we are done with this table and we move along
            out.push(tbl.join('\n'));
            continue;
          }
        }
        out.push(line);
      }
      return out.join('\n');
    };
    return [
    {
      type: 'lang',
      filter: filter
    }
    ];
  };

  // Client-side export
  if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.table = table; }
  // Server-side export
  if (typeof module !== 'undefined') {
    module.exports = table;
  }
}());
<|endoftext|>


<commit_before>'use strict';

import htmlparser from './htmlparser2.js';

export default class upndown {

    constructor({ decodeEntities = true } = {}) {
        this.decodeEntities = decodeEntities;
        this.init()
    }

    init() {
        this.olstack = [];
        this.inlineelements = ['strong', 'b', 'i', 'em', 'u', 'a', 'img', 'code'];
        this.htmlblocklevelelement = ['div', 'iframe', 'script'];
        this.tabindent = '    ';
        this.nbsp = '\u0000';
        this.bullet = "* "
    }

    parse(html, cbk) {
        let handler = new htmlparser.DomHandler(function(err, dom) {
            if(err) { return cbk(err, null); }
            return cbk(null, dom);
        }, { withDomLvl1: false, withStartIndices: false });

        let p = new htmlparser.Parser(handler, { decodeEntities: this.decodeEntities });
        p.write(html);
        p.end();
    }

    convert(html, cbk, options) {
      return new Promise(resolve => {
        if (!(cbk instanceof Function)) {
          options = cbk;
          cbk = function(err, md) { resolve(md || err) }
        }
        this.parse(html, function(err, dom) {
            if(err) { return cbk(err, null); }
            return this.convertDom(dom, function(err2, markdown) {
                if(err2) { return cbk(err2, null); }
                return cbk(null, markdown);
            }, options);
        }.bind(this));
      })
    }

    convertDom(dom, cbk, { keepHtml = false } = {}) {
        this.walkNodes(dom, { keepHtml })
            .then(function(markdown) {
                if(!markdown) { markdown = ''; }
                let regx = new RegExp(this.nbsp, 'g');
                cbk(null, markdown.trim().replace(regx, ' '));
            }.bind(this))
            .catch(function(err) {
                debugger
                cbk(err, null);
            });
    }

    walkNodes(nodes, options) {

        let self = this;

        return new Promise(function(topres, toprej) {
            let promises = [];
            for(let nodekey in nodes) {
                promises.push(new Promise(function(resolve, reject) { self.walkNode(resolve, reject, options, nodes[nodekey]); }));
            }

            Promise.all(promises)
                .then(function(results) { topres(results.join('')); })
                .catch(function(err) { toprej(err); });
        }).catch(function(err) { throw err; });
    }

    walkNode(resolve, reject, options, lenode) {

        if(lenode && lenode.type == "comment") {
          resolve("\n<!-- " + lenode.data + " -->")
        } else if(this.isText(lenode)) {
            resolve(this.text(lenode));
        } else {
            this.walkNodes(lenode.children, options)
                .then(function(innerMarkdown) { this.wrapNode(resolve, reject, options, lenode, innerMarkdown); }.bind(this))
                .catch(function(err) { reject(err); });
        }
    }

    wrapNode(resolve, reject, options, lenode, innerMarkdown) {

        let markdown = '';
        let method = 'wrap_' + lenode.name;

        if(method in this) {
            markdown = this[method](lenode, innerMarkdown);
        } else {
            if(options.keepHtml) {
                markdown = this.wrap_generic(lenode, innerMarkdown);
            } else {
                markdown = innerMarkdown;
            }
        }

        // Collapsing margins between block elements into a single line.
        // Pre-margins between an inline element and it's next sibling block are handled here also
        // Block-level elements handle themselves their post-margin
        // This is so because we're *descending* the dom tree :)

        let prevNonBlankText = this.getPreviousSiblingNonBlankText(lenode);
        if(prevNonBlankText) {
            let isPrevNonBlankTextBlock = this.isBlock(prevNonBlankText);
            if(this.isInline(lenode)) {
                // current node is inline, previous was block : adding an extra new line
                if(isPrevNonBlankTextBlock) { markdown = '\n' + markdown; }
            } else if(lenode.name !== 'br' && !this.isList(lenode) && this.isBlock(lenode)) {
                // current node is block, previous was inline or text : adding an extra new line
                if(!isPrevNonBlankTextBlock) { markdown = '\n' + markdown; }
            }
        }

        resolve(markdown);
    }

    // handlers

    allText(node) {
      let text = node.data || "";
      if (node.children) {
        node.children.forEach(ea => {
          text += this.allText(ea)
        })
      }
      return text
    }

    text(node) {
        let text = node.data;

        if(!text) { return ''; }

        if(this.hasAncestorOfType(node, ['code', 'pre'])) { return text; }

        // normalize whitespace

        if(node.prev) {
            if(this.isInline(node.prev)) {
                text = text.replace(/^\n+/, ' ');    // trimming newlines (would be converted to untrimmed spaces otherwise)
            } else {
                text = text.replace(/^\n+/, '');
            }
        }

        if(node.next) {
            if(this.isInline(node.next)) {
                text = text.replace(/\n+$/, ' ');    // trimming newlines (would be converted to untrimmed spaces otherwise)
            } else {
                text = text.replace(/\n+$/, '');
            }
        }

        text = text
            .replace('\n', ' ')         // converting inner newlines to spaces
            .replace(/\s+/g, ' ');      // converting sequences of whitespace to single spaces

        if(
            // if prev node is block, this node is not displayed on the same line, so left-trim
            (node.prev && this.isBlock(node.prev)) ||

            // if current node is block, this node is not displayed on the same line either, so left-trim
            (node.parent && this.isBlock(node.parent) && this.isFirstChild(node))
        ) {
            text = text.replace(/^\s*/, '');
        }

        if(node.parent && this.isBlock(node.parent) && this.isLastChild(node)) {
            text = text.replace(/\s*$/, '');
        }

        return text;
    }

    wrap_generic(node, markdown) {

        let htmlattribs = '';
        // if (!node.type == "comment") {
        //   return "<!-- " + node.textContent + " -->"
        // }

        let attrs = Object.keys(node.attribs);
        for(let attrnamekey in attrs) {
            htmlattribs += " " + attrs[attrnamekey] + '="' + node.attribs[attrs[attrnamekey]] + '"';
        }

        return '<' + node.name + htmlattribs + '>' + markdown.replace(/\s+/gm, ' ') + '</' + node.name + '>' + (this.isHtmlBlockLevelElement(node.name) ? '\n' : '');
        //return markdown;
    }

    // Block level elements

    wrap_h1(node, markdown) { return '\n# ' + markdown + '\n'; }
    wrap_h2(node, markdown) { return '\n## ' + markdown + '\n'; }
    wrap_h3(node, markdown) { return '\n### ' + markdown + '\n'; }
    wrap_h4(node, markdown) { return '\n#### ' + markdown + '\n'; }
    wrap_h5(node, markdown) { return '\n##### ' + markdown + '\n'; }
    wrap_h6(node, markdown) { return '\n###### ' + markdown + '\n'; }

    wrap_blockquote(node, markdown) { return '\n' + markdown.trim().replace(/^/gm, '> ') + '\n'; }
    wrap_pre(node, markdown) { return '\n' + markdown.trim().replace(/^/gm, this.tabindent).replace(/ /g, this.nbsp) + '\n'; }

    wrap_code(node, markdown) {
        if(this.hasAncestorOfType(node, ['pre'])) {
            return markdown;
        }

        return '`' + markdown.trim() + '`';
    }

    wrap_ul(node, markdown) { return '\n' + markdown.trim() + '\n'; }
    wrap_ol(node, markdown) { return this.wrap_ul(node, markdown); }
    wrap_li(node, markdown) {

        let bullet = this.bullet;

        if(node.parent && node.parent.type === 'tag' && node.parent.name === 'ol') {
            let k = 1;
            let n = node;
            while(n.prev) {
                if(n.prev.type === 'tag' && n.prev.name === 'li') { k++; }
                n = n.prev;
            }

            bullet = k + '. ';
        }

        let firstChildNonBlankText = this.getFirstChildNonBlankText(node);
        if(firstChildNonBlankText) {
            if(this.isList(firstChildNonBlankText)) {
                bullet = this.tabindent;
            } else if(this.isBlock(firstChildNonBlankText)) {
                // p in li: add newline before
                bullet = '\n' + bullet;
            } else {
                let prevsibling = this.getPreviousSiblingNonBlankText(node);
                if(
                    prevsibling && prevsibling.type === 'tag' && prevsibling.name === 'li' &&
                    this.isBlock(this.getFirstChildNonBlankText(prevsibling))
                ) {
                    bullet = '\n' + bullet;
                }
            }
        }

        return bullet + markdown.replace(/^/gm, this.tabindent).trim() + '\n';
    }

    wrap_p(node, markdown) { return '\n' + markdown + '\n'; }

    wrap_br(/*node, markdown*/) { return '  \n'; }

    wrap_hr(/*node, markdown*/) { return '\n* * *\n'; }

    // Inline elements

    wrap_strong(node, markdown) { return '**' + markdown + '**'; }
    wrap_b(node, markdown) { return this.wrap_strong(node, markdown); }

    wrap_em(node, markdown) { return '*' + markdown + '*'; }
    wrap_i(node, markdown) { return this.wrap_em(node, markdown); }

    wrap_a(node, markdown) {

        let url = this.getAttrOrFalse('href', node);
        let title = this.getAttrOrFalse('title', node);

        if (!url) {
            return markdown;
        } else if (url && url === markdown && (!title || title === '')) {
            return '<' + url + '>';
        } else if ((url === markdown || url.replace(/^mailto:/, '') === markdown) && (!title || title === '')) {
            return '<' + url.replace(/^mailto:/, '') + '>';
        }

        return '[' + markdown + '](' + (url ? url : '') + (title ? ' "' + title + '"' : '') + ')';
    }

    wrap_img(node/*, markdown*/) {
        let alt = this.getAttrOrFalse('alt', node);
        let src = this.getAttrOrFalse('src', node);
        let title = this.getAttrOrFalse('title', node);
        return '![' + (alt ? alt : '') + '](' + (src ? src : '') + (title ? ' "' + title + '"' : '') + ')';
    }

    // helpers

    hasAncestorOfType(node, tagnames) {

        let parent = node.parent;
        while (parent) {
            if (tagnames.indexOf(parent.name) > -1) { return true; }
            parent = parent.parent;
        }

        return false;
    }

    isInline(node) {
        return node && node.type === 'tag' && this.inlineelements.indexOf(node.name) >= 0;
    }

    isBlock(node) {
        return node && (node.type === 'tag' || node.type === 'script') && !this.isInline(node);
    }

    isText(node) {
        return node && node.type === 'text';
    }

    isList(node) {
        return node && node.type === 'tag' && (node.name === 'ul' || node.name === 'ol');
    }

    isHtmlBlockLevelElement(tag) {
        return this.htmlblocklevelelement.indexOf(tag) >= 0;
    }

    getPreviousSiblingNonBlankText(node) {

        let prevsibling = node;
        let go = true;

        while (go) {

            if (prevsibling) {
                prevsibling = prevsibling.prev;
            }

            if (prevsibling && (prevsibling.type !== 'text' || prevsibling.data.trim() !== '')) {
                return prevsibling;
            }

            if (!(prevsibling && !this.isFirstChildNonText(prevsibling))) {
                break;
            }
        }

        return null;
    }

    getFirstChildNonText(node) {
        let i = 0;

        while (i < node.children.length) {
            if (node.children[i] && node.children[i].type !== 'text') {
                return node.children[i];
            }
            i++;
        }

        return null;
    }

    getFirstChildNonBlankText(node) {
        let i = 0;

        while (i < node.children.length) {
            if (node.children[i] && node.children[i].type !== 'text' || node.children[i].data.trim() !== '') {
                return node.children[i];
            }
            i++;
        }

        return null;
    }

    isFirstChild(node) {
        return !(!!node && !!node.prev);
    }

    isFirstChildNonText(node) {
        return node.parent && (this.getFirstChildNonText(node.parent) === node);
    }

    isLastChild(node) {
        return !(node.next);
    }

    getAttrOrFalse(attr, node) {
        if(attr in node.attribs) {
            return node.attribs[attr];
        }

        return false;
    }
}
<commit_msg>fix comment bug in upndown<commit_after>'use strict';

import htmlparser from './htmlparser2.js';

export default class upndown {

    constructor({ decodeEntities = true } = {}) {
        this.decodeEntities = decodeEntities;
        this.init()
    }

    init() {
        this.olstack = [];
        this.inlineelements = ['strong', 'b', 'i', 'em', 'u', 'a', 'img', 'code'];
        this.htmlblocklevelelement = ['div', 'iframe', 'script'];
        this.tabindent = '    ';
        this.nbsp = '\u0000';
        this.bullet = "* "
    }

    parse(html, cbk) {
        let handler = new htmlparser.DomHandler(function(err, dom) {
            if(err) { return cbk(err, null); }
            return cbk(null, dom);
        }, { withDomLvl1: false, withStartIndices: false });

        let p = new htmlparser.Parser(handler, { decodeEntities: this.decodeEntities });
        p.write(html);
        p.end();
    }

    convert(html, cbk, options) {
      return new Promise(resolve => {
        if (!(cbk instanceof Function)) {
          options = cbk;
          cbk = function(err, md) { resolve(md || err) }
        }
        this.parse(html, function(err, dom) {
            if(err) { return cbk(err, null); }
            return this.convertDom(dom, function(err2, markdown) {
                if(err2) { return cbk(err2, null); }
                return cbk(null, markdown);
            }, options);
        }.bind(this));
      })
    }

    convertDom(dom, cbk, { keepHtml = false } = {}) {
        this.walkNodes(dom, { keepHtml })
            .then(function(markdown) {
                if(!markdown) { markdown = ''; }
                let regx = new RegExp(this.nbsp, 'g');
                cbk(null, markdown.trim().replace(regx, ' '));
            }.bind(this))
            .catch(function(err) {
                debugger
                cbk(err, null);
            });
    }

    walkNodes(nodes, options) {

        let self = this;

        return new Promise(function(topres, toprej) {
            let promises = [];
            for(let nodekey in nodes) {
                promises.push(new Promise(function(resolve, reject) { self.walkNode(resolve, reject, options, nodes[nodekey]); }));
            }

            Promise.all(promises)
                .then(function(results) { topres(results.join('')); })
                .catch(function(err) { toprej(err); });
        }).catch(function(err) { throw err; });
    }

    walkNode(resolve, reject, options, lenode) {

        if(lenode && lenode.type == "comment") {
          resolve("\n<!--" + lenode.data + "-->")
        } else if(this.isText(lenode)) {
            resolve(this.text(lenode));
        } else {
            this.walkNodes(lenode.children, options)
                .then(function(innerMarkdown) { this.wrapNode(resolve, reject, options, lenode, innerMarkdown); }.bind(this))
                .catch(function(err) { reject(err); });
        }
    }

    wrapNode(resolve, reject, options, lenode, innerMarkdown) {

        let markdown = '';
        let method = 'wrap_' + lenode.name;

        if(method in this) {
            markdown = this[method](lenode, innerMarkdown);
        } else {
            if(options.keepHtml) {
                markdown = this.wrap_generic(lenode, innerMarkdown);
            } else {
                markdown = innerMarkdown;
            }
        }

        // Collapsing margins between block elements into a single line.
        // Pre-margins between an inline element and it's next sibling block are handled here also
        // Block-level elements handle themselves their post-margin
        // This is so because we're *descending* the dom tree :)

        let prevNonBlankText = this.getPreviousSiblingNonBlankText(lenode);
        if(prevNonBlankText) {
            let isPrevNonBlankTextBlock = this.isBlock(prevNonBlankText);
            if(this.isInline(lenode)) {
                // current node is inline, previous was block : adding an extra new line
                if(isPrevNonBlankTextBlock) { markdown = '\n' + markdown; }
            } else if(lenode.name !== 'br' && !this.isList(lenode) && this.isBlock(lenode)) {
                // current node is block, previous was inline or text : adding an extra new line
                if(!isPrevNonBlankTextBlock) { markdown = '\n' + markdown; }
            }
        }

        resolve(markdown);
    }

    // handlers

    allText(node) {
      let text = node.data || "";
      if (node.children) {
        node.children.forEach(ea => {
          text += this.allText(ea)
        })
      }
      return text
    }

    text(node) {
        let text = node.data;

        if(!text) { return ''; }

        if(this.hasAncestorOfType(node, ['code', 'pre'])) { return text; }

        // normalize whitespace

        if(node.prev) {
            if(this.isInline(node.prev)) {
                text = text.replace(/^\n+/, ' ');    // trimming newlines (would be converted to untrimmed spaces otherwise)
            } else {
                text = text.replace(/^\n+/, '');
            }
        }

        if(node.next) {
            if(this.isInline(node.next)) {
                text = text.replace(/\n+$/, ' ');    // trimming newlines (would be converted to untrimmed spaces otherwise)
            } else {
                text = text.replace(/\n+$/, '');
            }
        }

        text = text
            .replace('\n', ' ')         // converting inner newlines to spaces
            .replace(/\s+/g, ' ');      // converting sequences of whitespace to single spaces

        if(
            // if prev node is block, this node is not displayed on the same line, so left-trim
            (node.prev && this.isBlock(node.prev)) ||

            // if current node is block, this node is not displayed on the same line either, so left-trim
            (node.parent && this.isBlock(node.parent) && this.isFirstChild(node))
        ) {
            text = text.replace(/^\s*/, '');
        }

        if(node.parent && this.isBlock(node.parent) && this.isLastChild(node)) {
            text = text.replace(/\s*$/, '');
        }

        return text;
    }

    wrap_generic(node, markdown) {

        let htmlattribs = '';
        // if (!node.type == "comment") {
        //   return "<!-- " + node.textContent + " -->"
        // }

        let attrs = Object.keys(node.attribs);
        for(let attrnamekey in attrs) {
            htmlattribs += " " + attrs[attrnamekey] + '="' + node.attribs[attrs[attrnamekey]] + '"';
        }

        return '<' + node.name + htmlattribs + '>' + markdown.replace(/\s+/gm, ' ') + '</' + node.name + '>' + (this.isHtmlBlockLevelElement(node.name) ? '\n' : '');
        //return markdown;
    }

    // Block level elements

    wrap_h1(node, markdown) { return '\n# ' + markdown + '\n'; }
    wrap_h2(node, markdown) { return '\n## ' + markdown + '\n'; }
    wrap_h3(node, markdown) { return '\n### ' + markdown + '\n'; }
    wrap_h4(node, markdown) { return '\n#### ' + markdown + '\n'; }
    wrap_h5(node, markdown) { return '\n##### ' + markdown + '\n'; }
    wrap_h6(node, markdown) { return '\n###### ' + markdown + '\n'; }

    wrap_blockquote(node, markdown) { return '\n' + markdown.trim().replace(/^/gm, '> ') + '\n'; }
    wrap_pre(node, markdown) { return '\n' + markdown.trim().replace(/^/gm, this.tabindent).replace(/ /g, this.nbsp) + '\n'; }

    wrap_code(node, markdown) {
        if(this.hasAncestorOfType(node, ['pre'])) {
            return markdown;
        }

        return '`' + markdown.trim() + '`';
    }

    wrap_ul(node, markdown) { return '\n' + markdown.trim() + '\n'; }
    wrap_ol(node, markdown) { return this.wrap_ul(node, markdown); }
    wrap_li(node, markdown) {

        let bullet = this.bullet;

        if(node.parent && node.parent.type === 'tag' && node.parent.name === 'ol') {
            let k = 1;
            let n = node;
            while(n.prev) {
                if(n.prev.type === 'tag' && n.prev.name === 'li') { k++; }
                n = n.prev;
            }

            bullet = k + '. ';
        }

        let firstChildNonBlankText = this.getFirstChildNonBlankText(node);
        if(firstChildNonBlankText) {
            if(this.isList(firstChildNonBlankText)) {
                bullet = this.tabindent;
            } else if(this.isBlock(firstChildNonBlankText)) {
                // p in li: add newline before
                bullet = '\n' + bullet;
            } else {
                let prevsibling = this.getPreviousSiblingNonBlankText(node);
                if(
                    prevsibling && prevsibling.type === 'tag' && prevsibling.name === 'li' &&
                    this.isBlock(this.getFirstChildNonBlankText(prevsibling))
                ) {
                    bullet = '\n' + bullet;
                }
            }
        }

        return bullet + markdown.replace(/^/gm, this.tabindent).trim() + '\n';
    }

    wrap_p(node, markdown) { return '\n' + markdown + '\n'; }

    wrap_br(/*node, markdown*/) { return '  \n'; }

    wrap_hr(/*node, markdown*/) { return '\n* * *\n'; }

    // Inline elements

    wrap_strong(node, markdown) { return '**' + markdown + '**'; }
    wrap_b(node, markdown) { return this.wrap_strong(node, markdown); }

    wrap_em(node, markdown) { return '*' + markdown + '*'; }
    wrap_i(node, markdown) { return this.wrap_em(node, markdown); }

    wrap_a(node, markdown) {

        let url = this.getAttrOrFalse('href', node);
        let title = this.getAttrOrFalse('title', node);

        if (!url) {
            return markdown;
        } else if (url && url === markdown && (!title || title === '')) {
            return '<' + url + '>';
        } else if ((url === markdown || url.replace(/^mailto:/, '') === markdown) && (!title || title === '')) {
            return '<' + url.replace(/^mailto:/, '') + '>';
        }

        return '[' + markdown + '](' + (url ? url : '') + (title ? ' "' + title + '"' : '') + ')';
    }

    wrap_img(node/*, markdown*/) {
        let alt = this.getAttrOrFalse('alt', node);
        let src = this.getAttrOrFalse('src', node);
        let title = this.getAttrOrFalse('title', node);
        return '![' + (alt ? alt : '') + '](' + (src ? src : '') + (title ? ' "' + title + '"' : '') + ')';
    }

    // helpers

    hasAncestorOfType(node, tagnames) {

        let parent = node.parent;
        while (parent) {
            if (tagnames.indexOf(parent.name) > -1) { return true; }
            parent = parent.parent;
        }

        return false;
    }

    isInline(node) {
        return node && node.type === 'tag' && this.inlineelements.indexOf(node.name) >= 0;
    }

    isBlock(node) {
        return node && (node.type === 'tag' || node.type === 'script') && !this.isInline(node);
    }

    isText(node) {
        return node && node.type === 'text';
    }

    isList(node) {
        return node && node.type === 'tag' && (node.name === 'ul' || node.name === 'ol');
    }

    isHtmlBlockLevelElement(tag) {
        return this.htmlblocklevelelement.indexOf(tag) >= 0;
    }

    getPreviousSiblingNonBlankText(node) {

        let prevsibling = node;
        let go = true;

        while (go) {

            if (prevsibling) {
                prevsibling = prevsibling.prev;
            }

            if (prevsibling && (prevsibling.type !== 'text' || prevsibling.data.trim() !== '')) {
                return prevsibling;
            }

            if (!(prevsibling && !this.isFirstChildNonText(prevsibling))) {
                break;
            }
        }

        return null;
    }

    getFirstChildNonText(node) {
        let i = 0;

        while (i < node.children.length) {
            if (node.children[i] && node.children[i].type !== 'text') {
                return node.children[i];
            }
            i++;
        }

        return null;
    }

    getFirstChildNonBlankText(node) {
        let i = 0;

        while (i < node.children.length) {
            if (node.children[i] && node.children[i].type !== 'text' || node.children[i].data.trim() !== '') {
                return node.children[i];
            }
            i++;
        }

        return null;
    }

    isFirstChild(node) {
        return !(!!node && !!node.prev);
    }

    isFirstChildNonText(node) {
        return node.parent && (this.getFirstChildNonText(node.parent) === node);
    }

    isLastChild(node) {
        return !(node.next);
    }

    getAttrOrFalse(attr, node) {
        if(attr in node.attribs) {
            return node.attribs[attr];
        }

        return false;
    }
}
<|endoftext|>


<commit_before>(function(){
  'use strict';

  angular.module('cla.controllers')
    .controller('DiagnosisCtrl',
      ['$scope', 'Category', 'postal', 'eligibility_check',
        function($scope, Category, postal, eligibility_check) {
          // updates the state of case.diagnosis_state after each save
          function saveCallback(data) {
            $scope.case.diagnosis_state = data.state;

            if (!$scope.diagnosis.isInScopeUnknown()) {
              // refreshing the logs
              postal.publish({
                channel : 'models',
                topic   : 'Log.refresh'
              });
            }
          }

          // creates a new diagnosis
          $scope.createDiagnosis = function () {
            if (!$scope.case.diagnosis) {
              // creates the diagnosis object if it doesn't exist
              $scope.diagnosis.$save({
                'case_reference': $scope.case.reference
              }, function(data) {
                $scope.case.diagnosis = data.reference;
              });
            }
          };

          $scope.moveDown = function() {
            $scope.diagnosis.$move_down({
              'case_reference': $scope.case.reference
            }, saveCallback);
          };

          $scope.moveUp = function() {
            $scope.diagnosis.$move_up({
              'case_reference': $scope.case.reference
            }, saveCallback);
          };

          $scope.delete = function() {
            $scope.diagnosis.$delete({'case_reference': $scope.case.reference}, function() {
              $scope.case.diagnosis = null;
              eligibility_check.has_passported_proceedings_letter = false
              eligibility_check.$update($scope.case.reference)

              // refreshing the logs
              postal.publish({
                channel : 'models',
                topic   : 'Log.refresh'
              });
            });
          };

          // if choices.length === 1 => check it by default
          $scope.$watch('diagnosis.choices', function(newVal) {
            if (newVal && newVal.length === 1) {
              $scope.diagnosis.current_node_id = newVal[0].id;
            }
          });

          $scope.$watch('diagnosis.category', function(newVal) {
            if (!newVal) {
              $scope.category = null;
            } else {
              Category.get({code: $scope.diagnosis.category}).$promise.then(function(data) {
                $scope.category = data;
              });
            }
          });
        }
      ]
    );
})();
<commit_msg>Scroll scope form into view after clicking next for any of the questions<commit_after>(function(){
  'use strict';

  angular.module('cla.controllers')
    .controller('DiagnosisCtrl',
      ['$scope', 'Category', 'postal', 'eligibility_check',
        function($scope, Category, postal, eligibility_check) {
          // updates the state of case.diagnosis_state after each save
          function saveCallback(data) {
            $scope.case.diagnosis_state = data.state;

            if (!$scope.diagnosis.isInScopeUnknown()) {
              // refreshing the logs
              postal.publish({
                channel : 'models',
                topic   : 'Log.refresh'
              });
            }
          }

          // creates a new diagnosis
          $scope.createDiagnosis = function () {
            if (!$scope.case.diagnosis) {
              // creates the diagnosis object if it doesn't exist
              $scope.diagnosis.$save({
                'case_reference': $scope.case.reference
              }, function(data) {
                $scope.case.diagnosis = data.reference;
              });
            }
          };

          $scope.moveDown = function() {
            $scope.diagnosis.$move_down({
              'case_reference': $scope.case.reference
            }, saveCallback);

            // Mutation observer used to detect when form element has been changed
            // Due to new question (elements) being added and old question (elements) being removed
            var form = document.querySelector('form[name="diagnosis-form"]');

            var config = {
              childList: true
            };

            var callback = function(mutationsList, observer) {
              observer.disconnect()
              // Only scroll after form questions have been added to the form or removed
              form.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'start' });
              return;
            };

            var observer = new MutationObserver(callback);

            observer.observe(form, config);
          };

          $scope.moveUp = function() {
            $scope.diagnosis.$move_up({
              'case_reference': $scope.case.reference
            }, saveCallback);
          };

          $scope.delete = function() {
            $scope.diagnosis.$delete({'case_reference': $scope.case.reference}, function() {
              $scope.case.diagnosis = null;
              eligibility_check.has_passported_proceedings_letter = false
              eligibility_check.$update($scope.case.reference)

              // refreshing the logs
              postal.publish({
                channel : 'models',
                topic   : 'Log.refresh'
              });
            });
          };

          // if choices.length === 1 => check it by default
          $scope.$watch('diagnosis.choices', function(newVal) {
            if (newVal && newVal.length === 1) {
              $scope.diagnosis.current_node_id = newVal[0].id;
            }
          });

          $scope.$watch('diagnosis.category', function(newVal) {
            if (!newVal) {
              $scope.category = null;
            } else {
              Category.get({code: $scope.diagnosis.category}).$promise.then(function(data) {
                $scope.category = data;
              });
            }
          });
        }
      ]
    );
})();
<|endoftext|>


<commit_before>firstBy = (function() {
    /* mixin for the `thenBy` property */
    function extend(f) {
        f.thenBy = tb;
        return f;
    }
    /* adds a secondary compare function to the target function (`this` context)
       which is applied in case the first one returns 0 (equal)
       returns a new compare function, which has a `thenBy` method as well */
    function tb(y) {
        var x = this;
        return extend(function(a, b) {
            return x(a,b) || y(a,b);
        });
    }
    return extend;
})();
<commit_msg>Added Apache 2 license<commit_after>/***
   Copyright 2013 Teun Duynstee

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */
firstBy = (function() {
    /* mixin for the `thenBy` property */
    function extend(f) {
        f.thenBy = tb;
        return f;
    }
    /* adds a secondary compare function to the target function (`this` context)
       which is applied in case the first one returns 0 (equal)
       returns a new compare function, which has a `thenBy` method as well */
    function tb(y) {
        var x = this;
        return extend(function(a, b) {
            return x(a,b) || y(a,b);
        });
    }
    return extend;
})();
<|endoftext|>


<commit_before>var sidebarOpen = false;
var menuText = ["Menu", "Close"];
var menuElement = document.querySelector(".menu-link");
var sidebarElement = document.querySelector(".sidebar");
var mainElement = document.querySelector("main");
var headerElement = document.querySelector("header");
var rAF;

mainElement.addEventListener( "click", toggleSidebar, true );
menuElement.addEventListener( "click", toggleSidebar, false );
window.addEventListener( "hashchange", toggleSidebar, false );

function toggleSidebar ( event ) {
    // Don't toggle when there's nothing to hide.
    if (event.type === "hashchange" && !sidebarOpen) return;
    if (event.currentTarget === mainElement && !sidebarOpen) return;

    sidebarOpen = (!sidebarOpen);

    cancelAnimationFrame(rAF);
    rAF = requestAnimationFrame(function () {
        sidebarElement.classList.toggle( "sidebar-open" );
        headerElement.classList.toggle( "hidden" );
        menuElement.textContent = menuText[(sidebarOpen ? 1 : 0)];
    });
}<commit_msg>Move the sidebar logic to its own context<commit_after>function initSidebar () {
    var sidebarOpen = false;
    var menuText = ["Menu", "Close"];
    var menuElement = document.querySelector(".menu-link");
    var sidebarElement = document.querySelector(".sidebar");
    var mainElement = document.querySelector("main");
    var headerElement = document.querySelector("header");
    var rAF;

    mainElement.addEventListener( "click", toggleSidebar, true );
    menuElement.addEventListener( "click", toggleSidebar, false );
    window.addEventListener( "hashchange", toggleSidebar, false );

    function toggleSidebar ( event ) {
        // Don't toggle when there's nothing to hide.
        if (event.type === "hashchange" && !sidebarOpen) return;
        if (event.currentTarget === mainElement && !sidebarOpen) return;

        sidebarOpen = (!sidebarOpen);

        cancelAnimationFrame(rAF);
        rAF = requestAnimationFrame(function () {
            sidebarElement.classList.toggle( "sidebar-open" );
            headerElement.classList.toggle( "hidden" );
            menuElement.textContent = menuText[(sidebarOpen ? 1 : 0)];
        });
    }
}

initSidebar();<|endoftext|>


<commit_before>var express = require('express');
var app = express();
var http = require('http').Server(app);
var morality = require('verbal-morality');
var bullshit = require('industry-bullshit');

app.use(express.static('public'));

app.get('/level', (req, res) => {
  let score = morality(req.query.term) + (bullshit.score(req.query.term) * 2);
  let message = '';
  switch(score) {
    case 1:
      message = ' is slightly immoral. Be careful, this is a pee see work environment';
      break;
    case 2:
      message = ' is immoral. You are running the risk of being fined';
      break;
    case 3:
    case 4:
    case 5:
      message = ' is significantly immmoral. A fine has been issued.';
      break;
  }
  res.send(req.query.term + message);
});

app.get('/', (req, res) => res.sendFile(__dirname + "/index.html"));

http.listen(3030, () => console.log('listening on *:3030'));
<commit_msg>new 'listen' endpoint<commit_after>var express = require('express');
var app = express();
var http = require('http').Server(app);
var morality = require('verbal-morality');
var bullshit = require('industry-bullshit');

app.use(express.static('public'));

app.get('/level', (req, res) => {
  let score = morality(req.query.term) + (bullshit.score(req.query.term) * 2);
  let message = '';
  switch(score) {
    case 1:
      message = ' is slightly immoral. Be careful, this is a pee see work environment';
      break;
    case 2:
      message = ' is immoral. You are running the risk of being fined';
      break;
    case 3:
    case 4:
    case 5:
      message = ' is significantly immmoral. A fine has been issued.';
      break;
  }
  res.send(req.query.term + message);
});

app.get('/listen', (req, res) => {
  let moralityLevel = morality(req.query.term);
  let moralityFine = moralityLevel > 1 ? moralityLevel : 0;
  let moralityText = moralityLevel > 3 ? "intolerably immoral" : "unnacceptably immoral";
  let bullshitScore = bullshit.score(req.query.term);
  let bullshitText = bullshitScore > 3 ? "is complete nonsense" : "sounds a bit nonsensical";

  res.json({
    moralityLevel: moralityLevel,
    moralityFine: moralityFine,
    moralityText: moralityText,
    bullshitScore: bullshitScore,
    bullshitText: bullshitText
  });
});

app.get('/', (req, res) => res.sendFile(__dirname + "/index.html"));

http.listen(3030, () => console.log('listening on *:3030'));
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
  Actions are high-level executable behaviours that are typically
  triggered by users and represented as buttons or menus.

  Actions are installed as methods on the class, but contain more
  meta-information than regular methods. Meta-information includes
  information needed to surface to action in a meaningful way to
  users, and includes things like the label to appear in the button
  or menu, a speech-label for i18n, help text, dynamic functions to
  enable or disable and hide or unhide the UI associated with this Action.

  Actions implement the Action Design Pattern.
*/
foam.CLASS({
  package: 'foam.core',
  name: 'Action',
  requires: [
    'foam.core.ExpressionSlot',
  ],

  documentation: 'An Action is a method with extra GUI support.',

  properties: [
    {
      class: 'String',
      name: 'name',
      required: true
    },
    {
      class: 'String',
      name: 'label',
      expression: function(name) { return foam.String.labelize(name); }
    },
    {
      class: 'String',
      name: 'speechLabel',
      expression: function(label) { return label; }
    },
    {
      documentation: 'displayed on :hover',
      class: 'String',
      name: 'toolTip',
      expression: function(label) { return label; }
    },
    {
      name: 'icon'
    },
    {
      class: 'Boolean',
      name: 'confirmationRequired',
      documentation: 'If confirmation is required. Recommended for destructive actions.'
    },
    {
      class: 'String',
      name: 'iconFontFamily',
      value: 'Material Icons'
    },
    {
      class: 'String',
      name: 'iconFontClass',
      value: 'material-icons'
    },
    {
      class: 'String',
      name: 'iconFontName'
    },
    {
      class: 'Array',
      name: 'keyboardShortcuts'
    },
    {
      class: 'String',
      name: 'help'
    },
    {
      class: 'Boolean',
      name: 'isDefault',
      help: 'Indicates if this is the default action.',
      value: false
    },
    {
      class: 'Function',
      name: 'isAvailable',
      label: 'Available',
      help: 'Function to determine if action is available.',
      value: null
    },
    {
      class: 'Function',
      name: 'isEnabled',
      label: 'Enabled',
      help: 'Function to determine if action is enabled.',
      value: null
    },
    {
      class: 'Function',
      name: 'code',
      required: true,
      value: null
    }
  ],

  methods: [
    function isEnabledFor(data) {
      return this.isEnabled ?
        data.slot(this.isEnabled).get() :
        true;
    },

    function createIsEnabled$(data$) {
      return foam.core.ExpressionSlot.create({
        obj$: data$,
        code: this.isEnabled
      });
    },

    function isAvailableFor(data) {
      return this.isAvailable ?
        foam.Function.withArgs(this.isAvailable, data) :
        true ;
    },

    function createIsAvailable$(data$) {
      return foam.core.ExpressionSlot.create({
        obj$: data$,
        code: this.isAvailable
      });
    },

    function maybeCall(ctx, data) {
      if ( this.isEnabledFor(data) && this.isAvailableFor(data) ) {
        this.code.call(data, ctx, this);
        data && data.pub('action', this.name, this);
        return true;
      }

      return false;
    },

    function installInClass(c) {
      c.installConstant(this.name, this);
    },

    function installInProto(proto) {
      var action = this;
      proto[this.name] = function() {
        return action.maybeCall(this.__context__, this);
      };
    }
  ]
});

/** Add Action support to Model. */
foam.CLASS({
  refines: 'foam.core.Model',
  package: 'foam.core',
  name: 'ModelActionRefine',

  properties: [
    {
      class: 'AxiomArray',
      of: 'Action',
      name: 'actions',
      adaptArrayElement: function(o, prop) {
        return typeof o === 'function' ?
            foam.core.Action.create({name: o.name, code: o}) :
            this.lookup(prop.of).create(o) ;
      }
    }
  ]
});
<commit_msg>Make ActionView work with primitive types.<commit_after>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
  Actions are high-level executable behaviours that are typically
  triggered by users and represented as buttons or menus.

  Actions are installed as methods on the class, but contain more
  meta-information than regular methods. Meta-information includes
  information needed to surface to action in a meaningful way to
  users, and includes things like the label to appear in the button
  or menu, a speech-label for i18n, help text, dynamic functions to
  enable or disable and hide or unhide the UI associated with this Action.

  Actions implement the Action Design Pattern.
*/
foam.CLASS({
  package: 'foam.core',
  name: 'Action',
  requires: [
    'foam.core.ExpressionSlot',
  ],

  documentation: 'An Action is a method with extra GUI support.',

  properties: [
    {
      class: 'String',
      name: 'name',
      required: true
    },
    {
      class: 'String',
      name: 'label',
      expression: function(name) { return foam.String.labelize(name); }
    },
    {
      class: 'String',
      name: 'speechLabel',
      expression: function(label) { return label; }
    },
    {
      documentation: 'displayed on :hover',
      class: 'String',
      name: 'toolTip',
      expression: function(label) { return label; }
    },
    {
      name: 'icon'
    },
    {
      class: 'Boolean',
      name: 'confirmationRequired',
      documentation: 'If confirmation is required. Recommended for destructive actions.'
    },
    {
      class: 'String',
      name: 'iconFontFamily',
      value: 'Material Icons'
    },
    {
      class: 'String',
      name: 'iconFontClass',
      value: 'material-icons'
    },
    {
      class: 'String',
      name: 'iconFontName'
    },
    {
      class: 'Array',
      name: 'keyboardShortcuts'
    },
    {
      class: 'String',
      name: 'help'
    },
    {
      class: 'Boolean',
      name: 'isDefault',
      help: 'Indicates if this is the default action.',
      value: false
    },
    {
      class: 'Function',
      name: 'isAvailable',
      label: 'Available',
      help: 'Function to determine if action is available.',
      value: null
    },
    {
      class: 'Function',
      name: 'isEnabled',
      label: 'Enabled',
      help: 'Function to determine if action is enabled.',
      value: null
    },
    {
      class: 'Function',
      name: 'code',
      required: true,
      value: null
    }
  ],

  methods: [
    function isEnabledFor(data) {
      return this.isEnabled ?
        data.slot(this.isEnabled).get() :
        true;
    },

    function createIsEnabled$(data$) {
      return foam.core.ExpressionSlot.create({
        obj$: data$,
        code: this.isEnabled
      });
    },

    function isAvailableFor(data) {
      return this.isAvailable ?
        foam.Function.withArgs(this.isAvailable, data) :
        true ;
    },

    function createIsAvailable$(data$) {
      return foam.core.ExpressionSlot.create({
        obj$: data$,
        code: this.isAvailable
      });
    },

    function maybeCall(ctx, data) {
      if ( this.isEnabledFor(data) && this.isAvailableFor(data) ) {
        this.code.call(data, ctx, this);
        // primitive types won't have a pub method
        // Why are we publishing this event anyway? KGR
        data && data.pub && data.pub('action', this.name, this);
        return true;
      }

      return false;
    },

    function installInClass(c) {
      c.installConstant(this.name, this);
    },

    function installInProto(proto) {
      var action = this;
      proto[this.name] = function() {
        return action.maybeCall(this.__context__, this);
      };
    }
  ]
});

/** Add Action support to Model. */
foam.CLASS({
  refines: 'foam.core.Model',
  package: 'foam.core',
  name: 'ModelActionRefine',

  properties: [
    {
      class: 'AxiomArray',
      of: 'Action',
      name: 'actions',
      adaptArrayElement: function(o, prop) {
        return typeof o === 'function' ?
            foam.core.Action.create({name: o.name, code: o}) :
            this.lookup(prop.of).create(o) ;
      }
    }
  ]
});
<|endoftext|>