<commit_before>/* @flow */

import * as $logger from 'beaver-logger/client';

import { config, FPTI } from './config';
import { initLogger, checkForCommonErrors, setLogLevel, stringifyError } from './lib';
import { enableCheckoutIframe } from './components';
import { createPptmScript } from './lib/pptm';
import { isPayPalDomain } from './lib';

import { ZalgoPromise } from 'zalgo-promise/src';

function domainToEnv(domain : string) : ?string {
    for (let env of Object.keys(config.paypalUrls)) {
        if (config.paypalUrls[env] === domain) {
            return env;
        }
    }
}

function setDomainEnv(domain : string) {
    let currentDomainEnv = domainToEnv(domain);

    if (currentDomainEnv && currentDomainEnv !== 'test') {
        config.env = currentDomainEnv;
    }
}

setDomainEnv(`${window.location.protocol}//${window.location.host}`);

initLogger();

ZalgoPromise.onPossiblyUnhandledException(err => {

    $logger.error('unhandled_error', {
        stack: stringifyError(err),
        errtype: ({}).toString.call(err)
    });

    $logger.track({
        [ FPTI.KEY.ERROR_CODE ]: 'checkoutjs_error',
        [ FPTI.KEY.ERROR_DESC ]: stringifyError(err)
    });

    $logger.flush();
});

function getCurrentScript() : ? HTMLScriptElement {

    let scripts = Array.prototype.slice.call(document.getElementsByTagName('script'));

    for (let script of scripts) {
        if (script.src && script.getAttribute('src') === config.scriptUrl || script.hasAttribute('data-paypal-checkout')) {
            return script;
        }

        if (script.src && script.src.indexOf('paypal.checkout.v4.js') !== -1) {
            return script;
        }
    }

    if (document.currentScript) {
        $logger.debug(`current_script_not_recognized`, { src: document.currentScript.src });
    }
}

let currentScript = getCurrentScript();
let currentProtocol = window.location.protocol.split(':')[0];

type SetupOptions = {
    env? : ?string,
    stage? : ?string,
    apiStage? : ?string,
    paypalUrl? : ?string,
    state? : ?string,
    ppobjects? : ?boolean,
    lightbox? : ?boolean,
    logLevel? : ?string
};

export function setup({ env, stage, apiStage, paypalUrl, state, ppobjects, lightbox, logLevel } : SetupOptions = {}) {

    checkForCommonErrors();

    if (env) {
        if (!config.paypalUrls[env]) {
            throw new Error(`Invalid env: ${env}`);
        }

        delete config.env;
        config.env = env;
    }

    if (stage) {
        delete config.stage;
        config.stage = stage;
    }

    if (apiStage) {
        delete config.apiStage;
        config.apiStage = apiStage;
    }

    if (paypalUrl) {
        delete config.paypalUrl;
        config.paypalUrl = paypalUrl;
        setDomainEnv(config.paypalUrl);
    }

    if (state) {
        delete config.state;
        config.state = state;
    }

    if (ppobjects) {
        config.ppobjects = true;
    }

    if (lightbox) {
        enableCheckoutIframe();
    }

    if (logLevel) {
        setLogLevel(logLevel);
    } else {
        setLogLevel(config.logLevel);
    }

    if (!isPayPalDomain()) {
        createPptmScript();
    }

    $logger.info(`setup_${config.env}`);

    $logger.debug(`current_protocol_${currentProtocol}`);
}

$logger.track({
    [ FPTI.KEY.STATE ]: FPTI.STATE.LOAD,
    [ FPTI.KEY.TRANSITION ]: FPTI.TRANSITION.SCRIPT_LOAD
});

if (currentScript) {

    setup({
        env:        currentScript.getAttribute('data-env'),
        stage:      currentScript.getAttribute('data-stage'),
        apiStage:   currentScript.getAttribute('data-api-stage'),
        paypalUrl:  currentScript.getAttribute('data-paypal-url'),
        state:      currentScript.getAttribute('data-state'),
        lightbox:   currentScript.hasAttribute('data-enable-lightbox'),
        logLevel:   currentScript.getAttribute('data-log-level'),
        ppobjects:  true
    });

    let scriptProtocol = currentScript.src.split(':')[0];

    $logger.debug(`current_script_protocol_${scriptProtocol}`);
    $logger.debug(`current_script_${ currentProtocol === scriptProtocol ? 'match' : 'mismatch' }_protocol`);

} else {
    $logger.debug(`no_current_script`);

    if (document.currentScript) {
        $logger.debug(`current_script_not_recognized`, { src: document.currentScript.src });
    }
}
<commit_msg>Prevent infinite loop from log flushing<commit_after>/* @flow */

import * as $logger from 'beaver-logger/client';

import { config, FPTI } from './config';
import { initLogger, checkForCommonErrors, setLogLevel, stringifyError } from './lib';
import { enableCheckoutIframe } from './components';
import { createPptmScript } from './lib/pptm';
import { isPayPalDomain } from './lib';

import { ZalgoPromise } from 'zalgo-promise/src';

function domainToEnv(domain : string) : ?string {
    for (let env of Object.keys(config.paypalUrls)) {
        if (config.paypalUrls[env] === domain) {
            return env;
        }
    }
}

function setDomainEnv(domain : string) {
    let currentDomainEnv = domainToEnv(domain);

    if (currentDomainEnv && currentDomainEnv !== 'test') {
        config.env = currentDomainEnv;
    }
}

setDomainEnv(`${window.location.protocol}//${window.location.host}`);

initLogger();

ZalgoPromise.onPossiblyUnhandledException(err => {

    $logger.error('unhandled_error', {
        stack: stringifyError(err),
        errtype: ({}).toString.call(err)
    });

    $logger.track({
        [ FPTI.KEY.ERROR_CODE ]: 'checkoutjs_error',
        [ FPTI.KEY.ERROR_DESC ]: stringifyError(err)
    });

    $logger.flush().catch(err2 => {
        if (window.console) {
            try {
                if (window.console.error) {
                    window.console.error('Error flushing:', err2.stack || err2.toString());
                } else if (window.console.log) {
                    window.console.log('Error flushing:', err2.stack || err2.toString());
                }
            } catch (err3) {
                setTimeout(() => {
                    throw err3;
                }, 1);
            }
        }
    });
});

function getCurrentScript() : ? HTMLScriptElement {

    let scripts = Array.prototype.slice.call(document.getElementsByTagName('script'));

    for (let script of scripts) {
        if (script.src && script.getAttribute('src') === config.scriptUrl || script.hasAttribute('data-paypal-checkout')) {
            return script;
        }

        if (script.src && script.src.indexOf('paypal.checkout.v4.js') !== -1) {
            return script;
        }
    }

    if (document.currentScript) {
        $logger.debug(`current_script_not_recognized`, { src: document.currentScript.src });
    }
}

let currentScript = getCurrentScript();
let currentProtocol = window.location.protocol.split(':')[0];

type SetupOptions = {
    env? : ?string,
    stage? : ?string,
    apiStage? : ?string,
    paypalUrl? : ?string,
    state? : ?string,
    ppobjects? : ?boolean,
    lightbox? : ?boolean,
    logLevel? : ?string
};

export function setup({ env, stage, apiStage, paypalUrl, state, ppobjects, lightbox, logLevel } : SetupOptions = {}) {

    checkForCommonErrors();

    if (env) {
        if (!config.paypalUrls[env]) {
            throw new Error(`Invalid env: ${env}`);
        }

        delete config.env;
        config.env = env;
    }

    if (stage) {
        delete config.stage;
        config.stage = stage;
    }

    if (apiStage) {
        delete config.apiStage;
        config.apiStage = apiStage;
    }

    if (paypalUrl) {
        delete config.paypalUrl;
        config.paypalUrl = paypalUrl;
        setDomainEnv(config.paypalUrl);
    }

    if (state) {
        delete config.state;
        config.state = state;
    }

    if (ppobjects) {
        config.ppobjects = true;
    }

    if (lightbox) {
        enableCheckoutIframe();
    }

    if (logLevel) {
        setLogLevel(logLevel);
    } else {
        setLogLevel(config.logLevel);
    }

    if (!isPayPalDomain()) {
        createPptmScript();
    }

    $logger.info(`setup_${config.env}`);

    $logger.debug(`current_protocol_${currentProtocol}`);
}

$logger.track({
    [ FPTI.KEY.STATE ]: FPTI.STATE.LOAD,
    [ FPTI.KEY.TRANSITION ]: FPTI.TRANSITION.SCRIPT_LOAD
});

if (currentScript) {

    setup({
        env:        currentScript.getAttribute('data-env'),
        stage:      currentScript.getAttribute('data-stage'),
        apiStage:   currentScript.getAttribute('data-api-stage'),
        paypalUrl:  currentScript.getAttribute('data-paypal-url'),
        state:      currentScript.getAttribute('data-state'),
        lightbox:   currentScript.hasAttribute('data-enable-lightbox'),
        logLevel:   currentScript.getAttribute('data-log-level'),
        ppobjects:  true
    });

    let scriptProtocol = currentScript.src.split(':')[0];

    $logger.debug(`current_script_protocol_${scriptProtocol}`);
    $logger.debug(`current_script_${ currentProtocol === scriptProtocol ? 'match' : 'mismatch' }_protocol`);

} else {
    $logger.debug(`no_current_script`);

    if (document.currentScript) {
        $logger.debug(`current_script_not_recognized`, { src: document.currentScript.src });
    }
}
<|endoftext|>


<commit_before>var http = require("http").createServer(handler); // on req - hand
var io = require("socket.io").listen(http);         //socket library
var fs = require("fs");                             //variable for file system for providing html
var firmata = require("firmata");

console.log("Starting the code");

var board = new firmata.Board("/dev/ttyACM0", function(){
    console.log("Connecting to Arduino");
    console.log("Activation of pin 13");
    board.pinMode(13, board.MODES.OUTPUT);      // pin13 as out
});

function handler(req,res){
   fs.readFile(__dirname + "/6diod.html",
   function (err, data) {
    if (err) {
        res.writeHead(500, {"Content-Type":"text/plain"});
        return res.end("Error loading html page.");
        }

    res.writeHead(200);
    res.end(data);
    })

}

http.listen(8080); // server will listen on port 8080

io.sockets.on("connection", function(socket) {
    socket.on("commandToArduino", function(commandNo){
         if (commandNo == 0) {
            board.digitalWrite(13, board.LOW); // write LOW on pin 13
        }
        if (commandNo == "1") {
            board.digitalWrite(13, board.HIGH); // write HIGH on pin 13
        }
        if (commandNo == "2") {
            board.digitalWrite(8, board.LOW); // write LOW on pin 8
        }
        if (commandNo == "3") {
            board.digitalWrite(8, board.HIGH); // write HIGH on pin 8
        }
    });
});
<commit_msg>Delete 6diod.js<commit_after><|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2016-2020 Camptocamp SA
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

import {noModifierKeys, singleClick} from 'ol/events/condition.js';
import olGeomLineString from 'ol/geom/LineString.js';
import olGeomMultiPoint from 'ol/geom/MultiPoint.js';
import olGeomMultiLineString from 'ol/geom/MultiLineString.js';
import olGeomMultiPolygon from 'ol/geom/MultiPolygon.js';
import olGeomPoint from 'ol/geom/Point.js';
import olGeomPolygon from 'ol/geom/Polygon.js';
import {getTopLeft, getTopRight, getBottomLeft, getBottomRight} from 'ol/extent.js';
import {MAC} from 'ol/has.js';

/**
 * Return whether the passed event has the 'ctrl' key (or 'meta' key on Mac) pressed or not.
 * @param {JQueryEventObject|KeyboardEvent} evt Event.
 * @return {boolean}
 */
export function isEventUsinCtrlKey(evt) {
  if (!evt) {
    return false;
  }
  // Do not use evt.ctrlKey (or evt.metaKey on Mac) Because Firefox sometimes doesn't assign the ctrlKey.
  return MAC ? evt.key === 'Meta' : evt.key === 'Control';
}

/**
 * Same as `ol.events.condition.platformModifierKeyOnly` but for JQueryEventObject.
 * @param {JQueryEventObject} evt Event.
 * @return {boolean} True if only the platform modifier key (ctrl) is pressed.
 * @private
 */
export function isPlatformModifierKeyOnly(evt) {
  return !evt.altKey && isEventUsinCtrlKey(evt) && !evt.shiftKey;
}

/**
 * Same as `ol.events.condition.shiftKeyOnly` but for JQueryEventObject.
 * @param {JQueryEventObject} evt Event.
 * @return {boolean} True if only the shift key is pressed.
 * @private
 */
export function isShiftKeyOnly(evt) {
  return !evt.altKey && !isEventUsinCtrlKey(evt) && evt.shiftKey;
}

/**
 * Return whether the primary pointing device is coarse or 'false' if unsupported (Internet Explorer).
 * See https://developer.mozilla.org/en-US/docs/Web/CSS/@media/pointer
 * @return {boolean}
 */
export function hasCoarsePointingDevice() {
  return matchMedia('(pointer: coarse)').matches;
}

/**
 * @param {string[]} availableLanguages Available languages.
 * @return {string} The "best" language code.
 */
export function getBrowserLanguage(availableLanguages) {
  let browserLanguages = window.navigator.languages || [window.navigator.language];
  browserLanguages = browserLanguages.map((item) => item.substring(0, 2));
  // remove duplicated language codes
  browserLanguages = browserLanguages.filter((item, index, arr) => arr.indexOf(item) == index);
  const supportedLanguages = browserLanguages.filter((item) => availableLanguages.includes(item));
  return supportedLanguages[0];
}

/**
 * Utility method that converts a simple geometry to its multi equivalent. If
 * the geometry itself is already multi, it is returned as-is.
 * @param {import("ol/geom/Geometry.js").default} geometry A geometry
 * @return {import("ol/geom/Geometry.js").default} A multi geometry
 * @hidden
 */
export function toMulti(geometry) {
  /** @type {import("ol/geom/Geometry.js").default} */
  let multiGeom;
  if (geometry instanceof olGeomPoint) {
    const multiGeomPoint = new olGeomMultiPoint([]);
    multiGeomPoint.appendPoint(geometry);
    multiGeom = multiGeomPoint;
  } else if (geometry instanceof olGeomLineString) {
    const multiGeomLine = new olGeomMultiLineString([]);
    multiGeomLine.appendLineString(geometry);
    multiGeom = multiGeomLine;
  } else if (geometry instanceof olGeomPolygon) {
    const multiGeomPolygon = new olGeomMultiPolygon([]);
    multiGeomPolygon.appendPolygon(geometry);
    multiGeom = multiGeomPolygon;
  } else {
    multiGeom = geometry;
  }
  return multiGeom;
}

/**
 * Checks if on Safari.
 * @return {boolean} True if on Safari.
 * @hidden
 */
export function isSafari() {
  return navigator.userAgent.includes('Safari') && !navigator.userAgent.includes('Chrome');
}

/**
 * Takes a hex value and prepends a zero if it's a single digit.
 * @param {string} hex Hex value to prepend if single digit.
 * @return {string} hex value prepended with zero if it was single digit,
 *     otherwise the same value that was passed in.
 * @hidden
 */
export function colorZeroPadding(hex) {
  return hex.length == 1 ? `0${hex}` : hex;
}

/**
 * Converts a color from RGB to hex representation.
 * @param {number[]} rgb rgb representation of the color.
 * @return {string} hex representation of the color.
 * @hidden
 */
export function rgbArrayToHex(rgb) {
  const r = rgb[0];
  const g = rgb[1];
  const b = rgb[2];
  if (r != (r & 255) || g != (g & 255) || b != (b & 255)) {
    throw Error(`"(${r},${g},${b})" is not a valid RGB color`);
  }
  const hexR = colorZeroPadding(r.toString(16));
  const hexG = colorZeroPadding(g.toString(16));
  const hexB = colorZeroPadding(b.toString(16));
  return `#${hexR}${hexG}${hexB}`;
}

/**
 * Decode the encoded query string into a query data dictionary.
 * @param {string|undefined} queryString The queryString.
 * @return {Object<string, string>} The result.
 * @hidden
 */
export function decodeQueryString(queryString) {
  /** @type {Object<string, string>} */
  const queryData = {};
  if (queryString) {
    const pairs = queryString.substring(1).split('&');
    for (const pair of pairs) {
      const indexOfEquals = pair.indexOf('=');
      if (indexOfEquals >= 0) {
        const name = pair.substring(0, indexOfEquals);
        const value = pair.substring(indexOfEquals + 1);
        try {
          queryData[decodeURIComponent(name)] = decodeURIComponent(value);
        } catch (error) {
          // ignore URIError exception from decodeURIComponent
          console.error(`Malformed parameter: ${name}=${value}`);
        }
      } else {
        queryData[pair] = '';
      }
    }
  }
  return queryData;
}

/**
 * Encode the query data dictionary into an encoded query string.
 * @param {Object<string, string>} queryData The queryData,
 * @return {string} The result.
 * @hidden
 */
export function encodeQueryString(queryData) {
  const queryItem = [];
  for (const key in queryData) {
    const value = queryData[key];
    queryItem.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
  }
  return queryItem.join('&');
}

/**
 * Delete condition passed to the modify interaction
 * @param {import('ol/MapBrowserEvent.js').default<unknown>} event Browser event.
 * @return {boolean} The result.
 * @hidden
 */
export function deleteCondition(event) {
  return noModifierKeys(event) && singleClick(event);
}

/**
 * Takes an import("ol/extent.js").Extent and return an Array of
 * ol.Coordinate representing a rectangle polygon.
 * @param {import("ol/extent.js").Extent} extent The extent.
 * @return {Array.<import("ol/coordinate.js").Coordinate>} The Array of coordinate of the rectangle.
 */
export function extentToRectangle(extent) {
  const result = [
    getTopLeft(extent),
    getTopRight(extent),
    getBottomRight(extent),
    getBottomLeft(extent),
    getTopLeft(extent),
  ];
  return result;
}

/**
 * Return the screen DPI.
 * @return {number} The screen DPI.
 */
export function dpi() {
  // See:
  // - https://developer.mozilla.org/en/docs/Web/API/Window/devicePixelRatio
  // - https://www.html5rocks.com/en/mobile/high-dpi/
  // - https://www.w3.org/TR/css3-values/#absolute-lengths
  return 96;
}
<commit_msg>Better work around for ctrlKey events<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2016-2020 Camptocamp SA
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

import {noModifierKeys, singleClick} from 'ol/events/condition.js';
import olGeomLineString from 'ol/geom/LineString.js';
import olGeomMultiPoint from 'ol/geom/MultiPoint.js';
import olGeomMultiLineString from 'ol/geom/MultiLineString.js';
import olGeomMultiPolygon from 'ol/geom/MultiPolygon.js';
import olGeomPoint from 'ol/geom/Point.js';
import olGeomPolygon from 'ol/geom/Polygon.js';
import {getTopLeft, getTopRight, getBottomLeft, getBottomRight} from 'ol/extent.js';
import {MAC} from 'ol/has.js';

/**
 * Return whether the passed event has the 'ctrl' key (or 'meta' key on Mac) pressed or not.
 * @param {JQueryEventObject|KeyboardEvent} evt Event.
 * @return {boolean}
 */
export function isEventUsinCtrlKey(evt) {
  if (!evt) {
    return false;
  }
  // Check also evt.key because Firefox on Ubuntu sometimes doesn't assign the ctrlKey flag.
  // Don't check only the evt.key because pressing multiples keys at once shows only one key.
  return (MAC ? evt.metaKey : evt.ctrlKey) || evt.key === 'Control';
}

/**
 * Same as `ol.events.condition.platformModifierKeyOnly` but for JQueryEventObject.
 * @param {JQueryEventObject} evt Event.
 * @return {boolean} True if only the platform modifier key (ctrl) is pressed.
 * @private
 */
export function isPlatformModifierKeyOnly(evt) {
  return !evt.altKey && isEventUsinCtrlKey(evt) && !evt.shiftKey;
}

/**
 * Same as `ol.events.condition.shiftKeyOnly` but for JQueryEventObject.
 * @param {JQueryEventObject} evt Event.
 * @return {boolean} True if only the shift key is pressed.
 * @private
 */
export function isShiftKeyOnly(evt) {
  return !evt.altKey && !isEventUsinCtrlKey(evt) && evt.shiftKey;
}

/**
 * Return whether the primary pointing device is coarse or 'false' if unsupported (Internet Explorer).
 * See https://developer.mozilla.org/en-US/docs/Web/CSS/@media/pointer
 * @return {boolean}
 */
export function hasCoarsePointingDevice() {
  return matchMedia('(pointer: coarse)').matches;
}

/**
 * @param {string[]} availableLanguages Available languages.
 * @return {string} The "best" language code.
 */
export function getBrowserLanguage(availableLanguages) {
  let browserLanguages = window.navigator.languages || [window.navigator.language];
  browserLanguages = browserLanguages.map((item) => item.substring(0, 2));
  // remove duplicated language codes
  browserLanguages = browserLanguages.filter((item, index, arr) => arr.indexOf(item) == index);
  const supportedLanguages = browserLanguages.filter((item) => availableLanguages.includes(item));
  return supportedLanguages[0];
}

/**
 * Utility method that converts a simple geometry to its multi equivalent. If
 * the geometry itself is already multi, it is returned as-is.
 * @param {import("ol/geom/Geometry.js").default} geometry A geometry
 * @return {import("ol/geom/Geometry.js").default} A multi geometry
 * @hidden
 */
export function toMulti(geometry) {
  /** @type {import("ol/geom/Geometry.js").default} */
  let multiGeom;
  if (geometry instanceof olGeomPoint) {
    const multiGeomPoint = new olGeomMultiPoint([]);
    multiGeomPoint.appendPoint(geometry);
    multiGeom = multiGeomPoint;
  } else if (geometry instanceof olGeomLineString) {
    const multiGeomLine = new olGeomMultiLineString([]);
    multiGeomLine.appendLineString(geometry);
    multiGeom = multiGeomLine;
  } else if (geometry instanceof olGeomPolygon) {
    const multiGeomPolygon = new olGeomMultiPolygon([]);
    multiGeomPolygon.appendPolygon(geometry);
    multiGeom = multiGeomPolygon;
  } else {
    multiGeom = geometry;
  }
  return multiGeom;
}

/**
 * Checks if on Safari.
 * @return {boolean} True if on Safari.
 * @hidden
 */
export function isSafari() {
  return navigator.userAgent.includes('Safari') && !navigator.userAgent.includes('Chrome');
}

/**
 * Takes a hex value and prepends a zero if it's a single digit.
 * @param {string} hex Hex value to prepend if single digit.
 * @return {string} hex value prepended with zero if it was single digit,
 *     otherwise the same value that was passed in.
 * @hidden
 */
export function colorZeroPadding(hex) {
  return hex.length == 1 ? `0${hex}` : hex;
}

/**
 * Converts a color from RGB to hex representation.
 * @param {number[]} rgb rgb representation of the color.
 * @return {string} hex representation of the color.
 * @hidden
 */
export function rgbArrayToHex(rgb) {
  const r = rgb[0];
  const g = rgb[1];
  const b = rgb[2];
  if (r != (r & 255) || g != (g & 255) || b != (b & 255)) {
    throw Error(`"(${r},${g},${b})" is not a valid RGB color`);
  }
  const hexR = colorZeroPadding(r.toString(16));
  const hexG = colorZeroPadding(g.toString(16));
  const hexB = colorZeroPadding(b.toString(16));
  return `#${hexR}${hexG}${hexB}`;
}

/**
 * Decode the encoded query string into a query data dictionary.
 * @param {string|undefined} queryString The queryString.
 * @return {Object<string, string>} The result.
 * @hidden
 */
export function decodeQueryString(queryString) {
  /** @type {Object<string, string>} */
  const queryData = {};
  if (queryString) {
    const pairs = queryString.substring(1).split('&');
    for (const pair of pairs) {
      const indexOfEquals = pair.indexOf('=');
      if (indexOfEquals >= 0) {
        const name = pair.substring(0, indexOfEquals);
        const value = pair.substring(indexOfEquals + 1);
        try {
          queryData[decodeURIComponent(name)] = decodeURIComponent(value);
        } catch (error) {
          // ignore URIError exception from decodeURIComponent
          console.error(`Malformed parameter: ${name}=${value}`);
        }
      } else {
        queryData[pair] = '';
      }
    }
  }
  return queryData;
}

/**
 * Encode the query data dictionary into an encoded query string.
 * @param {Object<string, string>} queryData The queryData,
 * @return {string} The result.
 * @hidden
 */
export function encodeQueryString(queryData) {
  const queryItem = [];
  for (const key in queryData) {
    const value = queryData[key];
    queryItem.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
  }
  return queryItem.join('&');
}

/**
 * Delete condition passed to the modify interaction
 * @param {import('ol/MapBrowserEvent.js').default<unknown>} event Browser event.
 * @return {boolean} The result.
 * @hidden
 */
export function deleteCondition(event) {
  return noModifierKeys(event) && singleClick(event);
}

/**
 * Takes an import("ol/extent.js").Extent and return an Array of
 * ol.Coordinate representing a rectangle polygon.
 * @param {import("ol/extent.js").Extent} extent The extent.
 * @return {Array.<import("ol/coordinate.js").Coordinate>} The Array of coordinate of the rectangle.
 */
export function extentToRectangle(extent) {
  const result = [
    getTopLeft(extent),
    getTopRight(extent),
    getBottomRight(extent),
    getBottomLeft(extent),
    getTopLeft(extent),
  ];
  return result;
}

/**
 * Return the screen DPI.
 * @return {number} The screen DPI.
 */
export function dpi() {
  // See:
  // - https://developer.mozilla.org/en/docs/Web/API/Window/devicePixelRatio
  // - https://www.html5rocks.com/en/mobile/high-dpi/
  // - https://www.w3.org/TR/css3-values/#absolute-lengths
  return 96;
}
<|endoftext|>


<commit_before>/* @flow */

import * as $logger from 'beaver-logger/client';
import { bridge } from 'post-robot/src';

import { config, FPTI } from './config';
import { initLogger, checkForCommonErrors, setLogLevel, stringifyError, stringifyErrorMessage, getResourceLoadTime } from './lib';
import { createPptmScript } from './lib/pptm';
import { isPayPalDomain, isEligible, getDomainSetting, once } from './lib';

import { ZalgoPromise } from 'zalgo-promise/src';

function domainToEnv(domain : string) : ?string {
    for (let env of Object.keys(config.paypalUrls)) {
        if (config.paypalUrls[env] === domain) {
            return env;
        }
    }
}

function setDomainEnv(domain : string) {
    let currentDomainEnv = domainToEnv(domain);

    if (currentDomainEnv && currentDomainEnv !== 'test') {
        config.env = currentDomainEnv;
    }
}

setDomainEnv(`${window.location.protocol}//${window.location.host}`);

ZalgoPromise.onPossiblyUnhandledException(err => {

    $logger.error('unhandled_error', {
        stack: stringifyError(err),
        errtype: ({}).toString.call(err)
    });

    $logger.track({
        [ FPTI.KEY.ERROR_CODE ]: 'checkoutjs_error',
        [ FPTI.KEY.ERROR_DESC ]: stringifyErrorMessage(err)
    });

    $logger.flush().catch(err2 => {
        if (window.console) {
            try {
                if (window.console.error) {
                    window.console.error('Error flushing:', err2.stack || err2.toString());
                } else if (window.console.log) {
                    window.console.log('Error flushing:', err2.stack || err2.toString());
                }
            } catch (err3) {
                setTimeout(() => {
                    throw err3;
                }, 1);
            }
        }
    });
});

function getCurrentScript() : ? HTMLScriptElement {

    let scripts = Array.prototype.slice.call(document.getElementsByTagName('script'));

    for (let script of scripts) {
        if (script.src && script.src.replace(/^https?:/, '').split('?')[0] === config.scriptUrl || script.hasAttribute('data-paypal-checkout')) {
            return script;
        }

        if (script.src && script.src.indexOf('paypal.checkout.v4.js') !== -1) {
            return script;
        }
    }

    if (document.currentScript) {
        $logger.debug(`current_script_not_recognized`, { src: document.currentScript.src });
    }
}

let currentScript = getCurrentScript();
let currentProtocol = window.location.protocol.split(':')[0];

type ConfigOptions = {
    env? : ?string,
    stage? : ?string,
    apiStage? : ?string,
    state? : ?string,
    ppobjects? : ?boolean,
    logLevel? : ?string
};

function configure({ env, stage, apiStage, paypalUrl, state, ppobjects, logLevel } : ConfigOptions = {}) {

    if (env) {
        if (!config.paypalUrls[env]) {
            throw new Error(`Invalid env: ${env}`);
        }

        delete config.env;
        config.env = env;
    }

    if (stage) {
        delete config.stage;
        config.stage = stage;
    }

    if (apiStage) {
        delete config.apiStage;
        config.apiStage = apiStage;
    }

    if (state) {
        delete config.state;
        config.state = state;
    }

    if (ppobjects) {
        config.ppobjects = true;
    }

    if (logLevel) {
        setLogLevel(logLevel);
    } else {
        setLogLevel(config.logLevel);
    }
}

export let init = once(() => {

    if (!isEligible()) {
        $logger.warn('ineligible');
    }

    checkForCommonErrors();

    if (!isPayPalDomain()) {
        createPptmScript();
    }

    initLogger();

    if (getDomainSetting('force_bridge') && bridge && !isPayPalDomain()) {
        bridge.openBridge(config.postBridgeUrls[config.env], config.paypalDomains[config.env]);
    }

    $logger.info(`setup_${config.env}`);

    $logger.debug(`current_protocol_${currentProtocol}`);
});

export function setup(options : ConfigOptions = {}) {
    configure(options);
    init();
}

if (currentScript) {

    setup({
        env:        currentScript.getAttribute('data-env'),
        stage:      currentScript.getAttribute('data-stage'),
        apiStage:   currentScript.getAttribute('data-api-stage'),
        state:      currentScript.getAttribute('data-state'),
        logLevel:   currentScript.getAttribute('data-log-level'),
        ppobjects:  true
    });

    let scriptProtocol = currentScript.src.split(':')[0];

    let loadTime = getResourceLoadTime(currentScript.src);

    $logger.debug(`current_script_protocol_${scriptProtocol}`);
    $logger.debug(`current_script_protocol_${ currentProtocol === scriptProtocol ? 'match' : 'mismatch' }`);
    $logger.debug(`current_script_version_${ config.version.replace(/[^0-9a-zA-Z]+/g, '_') }`);

    if (loadTime && !isPayPalDomain()) {
        $logger.debug(`current_script_time`, { loadTime });
        $logger.debug(`current_script_time_${ Math.floor(loadTime / 1000) }`);
    }

    $logger.track({
        [ FPTI.KEY.STATE ]: FPTI.STATE.LOAD,
        [ FPTI.KEY.TRANSITION ]: FPTI.TRANSITION.SCRIPT_LOAD,
        [ FPTI.KEY.TRANSITION_TIME ]: loadTime
    });

} else {
    $logger.track({
        [ FPTI.KEY.STATE ]: FPTI.STATE.LOAD,
        [ FPTI.KEY.TRANSITION ]: FPTI.TRANSITION.SCRIPT_LOAD
    });

    $logger.debug(`no_current_script`);
    $logger.debug(`no_current_script_version_${ config.version.replace(/[^0-9a-zA-Z]+/g, '_') }`);

    if (document.currentScript) {
        $logger.debug(`current_script_not_recognized`, { src: document.currentScript.src });
    }

    setup();
}
<commit_msg>Load logging cleanup<commit_after>/* @flow */

import * as $logger from 'beaver-logger/client';
import { bridge } from 'post-robot/src';

import { config, FPTI } from './config';
import { initLogger, checkForCommonErrors, setLogLevel, stringifyError, stringifyErrorMessage, getResourceLoadTime } from './lib';
import { createPptmScript } from './lib/pptm';
import { isPayPalDomain, isEligible, getDomainSetting, once } from './lib';

import { ZalgoPromise } from 'zalgo-promise/src';

function domainToEnv(domain : string) : ?string {
    for (let env of Object.keys(config.paypalUrls)) {
        if (config.paypalUrls[env] === domain) {
            return env;
        }
    }
}

function setDomainEnv(domain : string) {
    let currentDomainEnv = domainToEnv(domain);

    if (currentDomainEnv && currentDomainEnv !== 'test') {
        config.env = currentDomainEnv;
    }
}

setDomainEnv(`${window.location.protocol}//${window.location.host}`);

ZalgoPromise.onPossiblyUnhandledException(err => {

    $logger.error('unhandled_error', {
        stack: stringifyError(err),
        errtype: ({}).toString.call(err)
    });

    $logger.track({
        [ FPTI.KEY.ERROR_CODE ]: 'checkoutjs_error',
        [ FPTI.KEY.ERROR_DESC ]: stringifyErrorMessage(err)
    });

    $logger.flush().catch(err2 => {
        if (window.console) {
            try {
                if (window.console.error) {
                    window.console.error('Error flushing:', err2.stack || err2.toString());
                } else if (window.console.log) {
                    window.console.log('Error flushing:', err2.stack || err2.toString());
                }
            } catch (err3) {
                setTimeout(() => {
                    throw err3;
                }, 1);
            }
        }
    });
});

function getCurrentScript() : ? HTMLScriptElement {

    let scripts = Array.prototype.slice.call(document.getElementsByTagName('script'));

    for (let script of scripts) {
        if (script.src && script.src.replace(/^https?:/, '').split('?')[0] === config.scriptUrl || script.hasAttribute('data-paypal-checkout')) {
            return script;
        }

        if (script.src && script.src.indexOf('paypal.checkout.v4.js') !== -1) {
            return script;
        }
    }

    if (document.currentScript) {
        $logger.debug(`current_script_not_recognized`, { src: document.currentScript.src });
    }
}

let currentScript = getCurrentScript();
let currentProtocol = window.location.protocol.split(':')[0];

type ConfigOptions = {
    env? : ?string,
    stage? : ?string,
    apiStage? : ?string,
    state? : ?string,
    ppobjects? : ?boolean,
    logLevel? : ?string
};

function configure({ env, stage, apiStage, paypalUrl, state, ppobjects, logLevel } : ConfigOptions = {}) {

    if (env) {
        if (!config.paypalUrls[env]) {
            throw new Error(`Invalid env: ${env}`);
        }

        delete config.env;
        config.env = env;
    }

    if (stage) {
        delete config.stage;
        config.stage = stage;
    }

    if (apiStage) {
        delete config.apiStage;
        config.apiStage = apiStage;
    }

    if (state) {
        delete config.state;
        config.state = state;
    }

    if (ppobjects) {
        config.ppobjects = true;
    }

    if (logLevel) {
        setLogLevel(logLevel);
    } else {
        setLogLevel(config.logLevel);
    }
}

export let init = once(() => {

    if (!isEligible()) {
        $logger.warn('ineligible');
    }

    checkForCommonErrors();

    if (!isPayPalDomain()) {
        createPptmScript();
    }

    initLogger();

    if (getDomainSetting('force_bridge') && bridge && !isPayPalDomain()) {
        bridge.openBridge(config.postBridgeUrls[config.env], config.paypalDomains[config.env]);
    }

    $logger.info(`setup_${config.env}`);

    $logger.debug(`current_protocol_${currentProtocol}`);
});

export function setup(options : ConfigOptions = {}) {
    configure(options);
    init();
}

if (currentScript) {
    setup({
        env:        currentScript.getAttribute('data-env'),
        stage:      currentScript.getAttribute('data-stage'),
        apiStage:   currentScript.getAttribute('data-api-stage'),
        state:      currentScript.getAttribute('data-state'),
        logLevel:   currentScript.getAttribute('data-log-level'),
        ppobjects:  true
    });

} else {
    setup();
}

if (!isPayPalDomain()) {

    if (currentScript) {

        let scriptProtocol = currentScript.src.split(':')[0];
        let loadTime = getResourceLoadTime(currentScript.src);

        $logger.debug(`current_script_protocol_${scriptProtocol}`);
        $logger.debug(`current_script_protocol_${ currentProtocol === scriptProtocol ? 'match' : 'mismatch' }`);
        $logger.debug(`current_script_version_${ config.version.replace(/[^0-9a-zA-Z]+/g, '_') }`);

        if (loadTime) {
            $logger.debug(`current_script_time`, { loadTime });
            $logger.debug(`current_script_time_${ Math.floor(loadTime / 1000) }`);
        }

        $logger.track({
            [ FPTI.KEY.STATE ]: FPTI.STATE.LOAD,
            [ FPTI.KEY.TRANSITION ]: FPTI.TRANSITION.SCRIPT_LOAD,
            [ FPTI.KEY.TRANSITION_TIME ]: loadTime
        });

    } else {

        $logger.debug(`no_current_script`);
        $logger.debug(`no_current_script_version_${ config.version.replace(/[^0-9a-zA-Z]+/g, '_') }`);

        if (document.currentScript) {
            $logger.debug(`current_script_not_recognized`, { src: document.currentScript.src });
        }

        $logger.track({
            [ FPTI.KEY.STATE ]: FPTI.STATE.LOAD,
            [ FPTI.KEY.TRANSITION ]: FPTI.TRANSITION.SCRIPT_LOAD
        });
    }
}
<|endoftext|>


<commit_before>const Gio = imports.gi.Gio;
const Path = imports.path;

let copy = function(obj2) {
    let ret = {}
    for (let i in obj2) {
	ret[i] = obj2[i];
    }
    return ret;
};

let copyList = function(list) {
    let ret = []
    for (let i in list)
	ret.push(list[i]);
    return ret;
};

let mergeProps = function(obj1, obj2) {
    if (obj1 === undefined || obj1 === null)
        obj1 = {};
    for (let i in obj2) {
	obj1[i] = obj2[i];
    }
    return obj1;
};

let parseProps = function(obj1, obj2) {
    let ret = {};
    for (let i in obj2) {
        if (obj1[i] == undefined) {
            ret[i] = obj2[i];
        } else {
            ret[i] = obj1[i];
            delete obj1[i];
        }
    }
    return ret;
};

let boxToString = function(box) {
    return '' + box.x1 + 'x' + box.y1 + ' -> ' + box.x2 + 'x' + box.y2;
};

let allocationBoxToString = function(box) {
    return '' + box.width + 'x' + box.height + ' @ ' + box.x + 'x' + box.y;
};

let levelToSpaces = function(level) {
    let ret = ''
    for (let i = 0; i < level; i++)
        ret += '   ';
    return ret;
};

let forEachInDirectory = function(directory, callback) {
    let enumerator = directory.enumerate_children('*',
                                                  Gio.FileQueryInfoFlags.NONE,
                                                  null);
    let fileInfo;
    while ((fileInfo = enumerator.next_file(null)) != null) {
        let child = enumerator.get_child(fileInfo);
        callback(child);
    }
    enumerator.close(null);
};

let buildPath = function(parent, child) {
    return parent + '/' + child;
};

let resolvePath = function(virtualPath) {
    let ret;
    if ((ret = /^library:\/\/(.*)/.exec(virtualPath)) != null)
        ret = Path.RESOURCE_DIR + '/' + ret[1];
    else if ((ret = /^local:\/\/(.*)/.exec(virtualPath)) != null)
        ret = Path.CURRENT_DIR + '/' + ret[1];
    else
        ret = virtualPath

    //log('path : ' + virtualPath + ' ->  ' + ret);

    return ret;
};

let resolveCachedPath = function(virtualPath) {
    let ret;
    if ((ret = /^library:\/\/(.*)/.exec(virtualPath)) != null)
        ret = Path.CACHE_DIR + '/library/' + ret[1];
    else if ((ret = /^local:\/\/(.*)/.exec(virtualPath)) != null)
        ret = Path.CACHE_DIR + '/local/' + ret[1]; // TODO: should be local
    else
        ret = virtualPath

    //log('cached path : ' + virtualPath + ' ->  ' + ret);

    return ret;
};

let loadTextFileContent = function(path) {
    let file = Gio.File.new_for_path(path);
    let [, content] = file.load_contents(null);
    return '' + content;
};

let saveTextFileContent = function(path, content) {
    let file = Gio.File.new_for_path(path);

    file.replace_contents(content,
                          null,
                          false,
                          Gio.FileCreateFlags.NONE, null,
                          null);
};

let parseJSON = function(data) {
    try {
        return JSON.parse(data);
    } catch (e) {
    }
    return null;
};

let guessLanguageFromFilename = function(filename) {
    if (/.*\.coffee$/.test(filename))
        return 'coffeescript';
    return 'javascript';
}
<commit_msg>runtime: init: make sure to create directories before writing files<commit_after>const Gio = imports.gi.Gio;
const Path = imports.path;

let copy = function(obj2) {
    let ret = {}
    for (let i in obj2) {
	ret[i] = obj2[i];
    }
    return ret;
};

let copyList = function(list) {
    let ret = []
    for (let i in list)
	ret.push(list[i]);
    return ret;
};

let mergeProps = function(obj1, obj2) {
    if (obj1 === undefined || obj1 === null)
        obj1 = {};
    for (let i in obj2) {
	obj1[i] = obj2[i];
    }
    return obj1;
};

let parseProps = function(obj1, obj2) {
    let ret = {};
    for (let i in obj2) {
        if (obj1[i] == undefined) {
            ret[i] = obj2[i];
        } else {
            ret[i] = obj1[i];
            delete obj1[i];
        }
    }
    return ret;
};

let boxToString = function(box) {
    return '' + box.x1 + 'x' + box.y1 + ' -> ' + box.x2 + 'x' + box.y2;
};

let allocationBoxToString = function(box) {
    return '' + box.width + 'x' + box.height + ' @ ' + box.x + 'x' + box.y;
};

let levelToSpaces = function(level) {
    let ret = ''
    for (let i = 0; i < level; i++)
        ret += '   ';
    return ret;
};

let forEachInDirectory = function(directory, callback) {
    let enumerator = directory.enumerate_children('*',
                                                  Gio.FileQueryInfoFlags.NONE,
                                                  null);
    let fileInfo;
    while ((fileInfo = enumerator.next_file(null)) != null) {
        let child = enumerator.get_child(fileInfo);
        callback(child);
    }
    enumerator.close(null);
};

let buildPath = function(parent, child) {
    return parent + '/' + child;
};

let resolvePath = function(virtualPath) {
    let ret;
    if ((ret = /^library:\/\/(.*)/.exec(virtualPath)) != null)
        ret = Path.RESOURCE_DIR + '/' + ret[1];
    else if ((ret = /^local:\/\/(.*)/.exec(virtualPath)) != null)
        ret = Path.CURRENT_DIR + '/' + ret[1];
    else
        ret = virtualPath

    //log('path : ' + virtualPath + ' ->  ' + ret);

    return ret;
};

let resolveCachedPath = function(virtualPath) {
    let ret;
    if ((ret = /^library:\/\/(.*)/.exec(virtualPath)) != null)
        ret = Path.CACHE_DIR + '/library/' + ret[1];
    else if ((ret = /^local:\/\/(.*)/.exec(virtualPath)) != null)
        ret = Path.CACHE_DIR + '/local/' + ret[1]; // TODO: should be local
    else
        ret = virtualPath

    //log('cached path : ' + virtualPath + ' ->  ' + ret);

    return ret;
};

let loadTextFileContent = function(path) {
    let file = Gio.File.new_for_path(path);
    let [, content] = file.load_contents(null);
    return '' + content;
};

let saveTextFileContent = function(path, content) {
    let file = Gio.File.new_for_path(path);
    let parent = file.get_parent();

    if (!parent.query_exists(null))
        parent.make_directory_with_parents(null);

    file.replace_contents(content,
                          null,
                          false,
                          Gio.FileCreateFlags.NONE, null,
                          null);
};

let parseJSON = function(data) {
    try {
        return JSON.parse(data);
    } catch (e) {
    }
    return null;
};

let guessLanguageFromFilename = function(filename) {
    if (/.*\.coffee$/.test(filename))
        return 'coffeescript';
    return 'javascript';
}
<|endoftext|>


<commit_before>export function arrayMove (arr, previousIndex, newIndex) {
    const array = arr.slice(0);
    if (newIndex >= array.length) {
        let k = newIndex - array.length;
        while ((k--) + 1) {
            array.push(undefined);
        }
    }
    array.splice(newIndex, 0, array.splice(previousIndex, 1)[0]);
    return array;
}

export const events = {
	start: ['touchstart', 'mousedown'],
	move: ['touchmove', 'mousemove'],
	end: ['touchend', 'touchcancel', 'mouseup']
};

export const vendorPrefix = (function () {
    if (typeof window === 'undefined' || typeof document === 'undefined') return ''; // server environment
    let styles = window.getComputedStyle(document.documentElement, '');
    const pre = (Array.prototype.slice
        .call(styles)
        .join('')
        .match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o'])
    )[1];

    switch (pre) {
        case 'ms':
            return 'ms';
        default:
            return (pre && pre.length) ? pre[0].toUpperCase() + pre.substr(1) : '';
    }
})();

export function closest(el, fn) {
    while (el) {
        if (fn(el)) return el;
        el = el.parentNode;
    }
}

export function limit(min, max, value) {
    if (value < min) {
        return min;
    }
    if (value > max) {
        return max;
    }
    return value;
}

function getCSSPixelValue(stringValue) {
    if (stringValue.substr(-2) === 'px') {
        return parseFloat(stringValue);
    }
    return 0;
}

export function getElementMargin(element) {
    const style = window.getComputedStyle(element);

    return {
        top: getCSSPixelValue(style.marginTop),
        right: getCSSPixelValue(style.marginRight),
        bottom: getCSSPixelValue(style.marginBottom),
        left: getCSSPixelValue(style.marginLeft)
    };
}

export function provideDisplayName(prefix, Component) {
    const componentName = Component.displayName || Component.name

    return componentName ? `${prefix}(${componentName})` : prefix;
}
<commit_msg>fix: workaround for mozilla bug:<commit_after>export function arrayMove (arr, previousIndex, newIndex) {
    const array = arr.slice(0);
    if (newIndex >= array.length) {
        let k = newIndex - array.length;
        while ((k--) + 1) {
            array.push(undefined);
        }
    }
    array.splice(newIndex, 0, array.splice(previousIndex, 1)[0]);
    return array;
}

export const events = {
	start: ['touchstart', 'mousedown'],
	move: ['touchmove', 'mousemove'],
	end: ['touchend', 'touchcancel', 'mouseup']
};

export const vendorPrefix = (function () {
    if (typeof window === 'undefined' || typeof document === 'undefined') return ''; // server environment
    // fix for:
    //    https://bugzilla.mozilla.org/show_bug.cgi?id=548397
    //    window.getComputedStyle() returns null inside an iframe with display: none
    // in this case return an array with a fake mozilla style in it.
    let styles = window.getComputedStyle(document.documentElement, '') || ['-moz-hidden-iframe'];
    const pre = (Array.prototype.slice
        .call(styles)
        .join('')
        .match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o'])
    )[1];

    switch (pre) {
        case 'ms':
            return 'ms';
        default:
            return (pre && pre.length) ? pre[0].toUpperCase() + pre.substr(1) : '';
    }
})();

export function closest(el, fn) {
    while (el) {
        if (fn(el)) return el;
        el = el.parentNode;
    }
}

export function limit(min, max, value) {
    if (value < min) {
        return min;
    }
    if (value > max) {
        return max;
    }
    return value;
}

function getCSSPixelValue(stringValue) {
    if (stringValue.substr(-2) === 'px') {
        return parseFloat(stringValue);
    }
    return 0;
}

export function getElementMargin(element) {
    const style = window.getComputedStyle(element);

    return {
        top: getCSSPixelValue(style.marginTop),
        right: getCSSPixelValue(style.marginRight),
        bottom: getCSSPixelValue(style.marginBottom),
        left: getCSSPixelValue(style.marginLeft)
    };
}

export function provideDisplayName(prefix, Component) {
    const componentName = Component.displayName || Component.name

    return componentName ? `${prefix}(${componentName})` : prefix;
}
<|endoftext|>


<commit_before>import fs from 'fs';
import minimist from 'minimist';
import logger from './logger';

const isStringJson = (string) => {
  try {
    JSON.parse(string);
  } catch (e) {
    return false;
  }
  return true;
};

const readFile = async (path) => {
  return new Promise((resolve) => {
    fs.readFile(path, { encoding: 'utf8' }, (err, data) => {
      if (err) {
        logger(`could not read ${path}`);
        resolve(null)
      } else {
        resolve(data);
      }
    });
  });
};

const getNodeEnv = () => {
  const args = minimist(process.argv.slice(2));
  let env = 'development';
  try {
    env = args.e
      .filter(arg => arg.split('=')[0] === 'NODE_ENV')[0].split('=')[1];
  } catch (e) {
    // NODE_ENV was not passed in (-e NODE_ENV=production)
    // ignore error, nodeEnv will be 'development'
  }
  return env;
};

const didPassInMeteorSettings = () => {
  const args = minimist(process.argv.slice(2));
  try {
    // TODO possibly better way of doing this
    args.e
      .filter(arg => arg.split('=')[0] === 'METEOR_SETTINGS')[0].split('=')[1];
  } catch (e) {
    // METEOR_SETTINGS argument was not passed
    return false;
  }
  return true;
};

export {
  isStringJson,
  readFile,
  getNodeEnv,
  didPassInMeteorSettings,
};
<commit_msg>added getArgs helper method<commit_after>import fs from 'fs';
import minimist from 'minimist';
import logger from './logger';

const isStringJson = (string) => {
  try {
    JSON.parse(string);
  } catch (e) {
    return false;
  }
  return true;
};

const readFile = async (path) => {
  return new Promise((resolve) => {
    fs.readFile(path, { encoding: 'utf8' }, (err, data) => {
      if (err) {
        logger(`could not read ${path}`);
        resolve(null)
      } else {
        resolve(data);
      }
    });
  });
};

const getNodeEnv = () => {
  const args = minimist(process.argv.slice(2));
  let env = 'development';
  try {
    env = args.e
      .filter(arg => arg.split('=')[0] === 'NODE_ENV')[0].split('=')[1];
  } catch (e) {
    // NODE_ENV was not passed in (-e NODE_ENV=production)
    // ignore error, nodeEnv will be 'development'
  }
  return env;
};

const didPassInMeteorSettings = () => {
  const args = minimist(process.argv.slice(2));
  try {
    // TODO possibly better way of doing this
    args.e
      .filter(arg => arg.split('=')[0] === 'METEOR_SETTINGS')[0].split('=')[1];
  } catch (e) {
    // METEOR_SETTINGS argument was not passed
    return false;
  }
  return true;
};

const getArgs = () => {
  const args = minimist(process.argv.slice(2));

  if (!args.e) {
    // no -e flag was passed
    return args;
  }

  // handle -e arguments. minimist returns a string to args.e if single flag is passed
  // and array if multiple are passed. This handles it so that getArgs() always returns
  // array for args.e regardless if one or more environment variables were passed
  let parsedEnvironmentArguments = [];
  const splitEnvironmentArgument = arg => arg.split('=');
  if (args.e && args.e instanceof Array) {
    parsedEnvironmentArguments = args.e.map(arg => splitEnvironmentArgument(arg));
  } else {
    parsedEnvironmentArguments = splitEnvironmentArgument(args.e);
  }
  return {
    ...args,
    e: parsedEnvironmentArguments,
  };
};

export {
  isStringJson,
  readFile,
  getNodeEnv,
  didPassInMeteorSettings,
  getArgs,
};
<|endoftext|>


<commit_before>'use strict';

import {hostname} from 'os';
import process from 'process';
import {name, version} from '../package.json';

/**
 * @returns current log level
 */

function getCurrentLogLevel() {
  return process.env.LOG_LEVEL || 'INFO'; // eslint-disable-line no-process-env
}

/**
 * Convert a log level name to a corresponding numerical value
 *
 * @param logLevel log level to convert
 * @returns numerical log level
 */

function getNumericalLogLevel(logLevel) {
  var logLevels = {
    OFF: 0,
    ERROR: 1,
    WARN: 2,
    WARNING: 2,
    INFO: 3,
    DEBUG: 4
  };

  var numericalLogLevel = logLevels[logLevel.toUpperCase()];
  return numericalLogLevel;
}

/**
 * Log as JSON to stdout
 *
 * @param level log level
 * @param msg message to log
 * @param args map of additional key/values to log
 */
function doLog(level, msg, args) {
  var currentNumericalLogLevel = getNumericalLogLevel(getCurrentLogLevel());
  var targetNumericalLogLevel = getNumericalLogLevel(level);

  var blob = {
    '@timestamp': (new Date()).toISOString(),
    '@version': 1,
    app: name,
    version: version,
    level: level.toUpperCase(),
    host: hostname(),
    pid: process.pid,
    msg: msg
  };

  if (currentNumericalLogLevel >= targetNumericalLogLevel) {
    console.log(JSON.stringify(Object.assign(blob, args))); // eslint-disable-line no-console
  }
}

export const log = {
  log: doLog,
  info: (msg, args) => doLog('info', msg, args),
  warn: (msg, args) => doLog('warn', msg, args),
  error: (msg, args) => doLog('error', msg, args),
  debug: (msg, args) => doLog('debug', msg, args)
};

export function userEncode(libraryId, userId) {
  return (userId || '') + '@' + (libraryId || '');
}

export function userDecode(username) {
  var splitPoint = username.lastIndexOf('@');
  var userId = username.substring(0, splitPoint);
  var libraryId = username.substring(splitPoint+1, username.length);
  var user = {libraryId: libraryId};

  if (userId) {
    user.id = userId;
  }

  return user;
}
<commit_msg>small change to make logging do as little as possible when not logging<commit_after>'use strict';

import {hostname} from 'os';
import process from 'process';
import {name, version} from '../package.json';

/**
 * @returns current log level
 */
function getCurrentLogLevel() {
  return process.env.LOG_LEVEL || 'INFO'; // eslint-disable-line no-process-env
}

/**
 * Convert a log level name to a corresponding numerical value
 *
 * @param logLevel log level to convert
 * @returns numerical log level
 */

function getNumericalLogLevel(logLevel) {
  var logLevels = {
    OFF: 0,
    ERROR: 1,
    WARN: 2,
    WARNING: 2,
    INFO: 3,
    DEBUG: 4
  };

  var numericalLogLevel = logLevels[logLevel.toUpperCase()];
  return numericalLogLevel;
}

/**
 * Log as JSON to stdout
 *
 * @param level log level
 * @param msg message to log
 * @param args map of additional key/values to log
 */
function doLog(level, msg, args) {
  var currentNumericalLogLevel = getNumericalLogLevel(getCurrentLogLevel());
  var targetNumericalLogLevel = getNumericalLogLevel(level);
  if (currentNumericalLogLevel < targetNumericalLogLevel) {
    return; // level low, do nothing
  }

  var blob = {
    '@timestamp': (new Date()).toISOString(),
    '@version': 1,
    app: name,
    version: version,
    level: level.toUpperCase(),
    host: hostname(),
    pid: process.pid,
    msg: msg
  };
  console.log(JSON.stringify(Object.assign(blob, args))); // eslint-disable-line no-console
}

export const log = {
  log: doLog,
  info: (msg, args) => doLog('info', msg, args),
  warn: (msg, args) => doLog('warn', msg, args),
  error: (msg, args) => doLog('error', msg, args),
  debug: (msg, args) => doLog('debug', msg, args)
};

export function userEncode(libraryId, userId) {
  return (userId || '') + '@' + (libraryId || '');
}

export function userDecode(username) {
  var splitPoint = username.lastIndexOf('@');
  var userId = username.substring(0, splitPoint);
  var libraryId = username.substring(splitPoint+1, username.length);
  var user = {libraryId: libraryId};

  if (userId) {
    user.id = userId;
  }

  return user;
}
<|endoftext|>


<commit_before>/* @flow */

import type {
  SchemaComposer,
  ObjectTypeComposer,
  InputTypeComposer,
  EnumTypeComposer,
  ComposeInputObjectTypeConfig,
  ComposeEnumTypeConfig,
  ObjectTypeComposeDefinition,
} from 'graphql-compose';
import { isFunction } from 'graphql-compose';
import type { ElasticMappingT, FieldsMapByElasticType } from './mappingConverter';

export type CommonOpts<TContext = {}> = {
  prefix?: string,
  postfix?: string,
  pluralFields?: string[],
  elasticIndex: string,
  elasticType: string,
  elasticClient: Object,
  fieldMap: FieldsMapByElasticType,
  sourceTC: ObjectTypeComposer<any, TContext>,
  schemaComposer: SchemaComposer<TContext>,
  getOrCreateOTC: (
    name: string,
    () => ObjectTypeComposeDefinition<any, TContext>
  ) => ObjectTypeComposer<any, TContext>,
  getOrCreateITC: (name: string, () => ComposeInputObjectTypeConfig) => InputTypeComposer<TContext>,
  getOrCreateETC: (name: string, () => ComposeEnumTypeConfig) => EnumTypeComposer<TContext>,
};

export function prepareCommonOpts<TContext>(
  schemaComposer: SchemaComposer<TContext>,
  opts: mixed = {}
): CommonOpts<TContext> {
  return {
    schemaComposer,
    getOrCreateOTC: (typeName, cfgOrThunk) => {
      return schemaComposer.getOrSet(typeName, () => {
        const tc = schemaComposer.createObjectTC(typeName);
        const cfg = isFunction(cfgOrThunk) ? (cfgOrThunk: any)() : cfgOrThunk;
        tc.setFields(cfg.fields);
        tc.setDescription(cfg.description);
        return tc;
      });
    },
    getOrCreateITC: (typeName, cfgOrThunk) => {
      return schemaComposer.getOrSet(typeName, () => {
        const tc = schemaComposer.createInputTC(typeName);
        const cfg = isFunction(cfgOrThunk) ? (cfgOrThunk: any)() : cfgOrThunk;
        tc.setFields(cfg.fields);
        tc.setDescription(cfg.description);
        return tc;
      });
    },
    getOrCreateETC: (typeName, cfgOrThunk) => {
      return schemaComposer.getOrSet(typeName, () => {
        const tc = schemaComposer.createEnumTC(typeName);
        const cfg = isFunction(cfgOrThunk) ? (cfgOrThunk: any)() : cfgOrThunk;
        tc.setFields(cfg.values);
        tc.setDescription(cfg.description);
        return tc;
      });
    },
    ...opts,
  };
}

export function getTypeName(name: string, opts: any): string {
  return `${(opts && opts.prefix) || 'Elastic'}${name}${(opts && opts.postfix) || ''}`;
}

// Remove newline multiline in descriptions
export function desc(str: string): string {
  return str.replace(/\n\s+/gi, ' ').replace(/^\s+/, '');
}

export function reorderKeys<T: Object>(obj: T, names: string[]): T {
  const orderedFields = {};
  const fields = { ...obj };
  names.forEach(name => {
    if (fields[name]) {
      orderedFields[name] = fields[name];
      delete fields[name];
    }
  });
  return { ...orderedFields, ...fields };
}

export type fetchElasticMappingOptsT = {
  elasticIndex: string,
  elasticType: string,
  elasticMapping: ElasticMappingT,
  elasticClient: Object,
};

export async function fetchElasticMapping(
  opts: fetchElasticMappingOptsT
): Promise<ElasticMappingT> {
  if (!opts.elasticIndex || typeof opts.elasticIndex !== 'string') {
    throw new Error('Must provide `elasticIndex` string parameter from your Elastic server.');
  }

  if (!opts.elasticType || typeof opts.elasticType !== 'string') {
    throw new Error('Must provide `elasticType` string parameter from your Elastic server.');
  }

  if (!opts.elasticClient) {
    throw new Error(
      'Must provide `elasticClient` Object parameter connected to your Elastic server.'
    );
  }

  const elasticMapping = (await opts.elasticClient.indices.getMapping({
    index: opts.elasticIndex,
    type: opts.elasticType,
  }))[opts.elasticIndex].mappings[opts.elasticType];

  return elasticMapping;
}
<commit_msg>fix: PageInfo must define one or more fields<commit_after>/* @flow */

import type {
  SchemaComposer,
  ObjectTypeComposer,
  InputTypeComposer,
  EnumTypeComposer,
  ComposeInputObjectTypeConfig,
  ComposeEnumTypeConfig,
  ObjectTypeComposeDefinition,
} from 'graphql-compose';
import { isFunction } from 'graphql-compose';
import type { ElasticMappingT, FieldsMapByElasticType } from './mappingConverter';

export type CommonOpts<TContext = {}> = {
  prefix?: string,
  postfix?: string,
  pluralFields?: string[],
  elasticIndex: string,
  elasticType: string,
  elasticClient: Object,
  fieldMap: FieldsMapByElasticType,
  sourceTC: ObjectTypeComposer<any, TContext>,
  schemaComposer: SchemaComposer<TContext>,
  getOrCreateOTC: (
    name: string,
    () => ObjectTypeComposeDefinition<any, TContext>
  ) => ObjectTypeComposer<any, TContext>,
  getOrCreateITC: (name: string, () => ComposeInputObjectTypeConfig) => InputTypeComposer<TContext>,
  getOrCreateETC: (name: string, () => ComposeEnumTypeConfig) => EnumTypeComposer<TContext>,
};

export function prepareCommonOpts<TContext>(
  schemaComposer: SchemaComposer<TContext>,
  opts: mixed = {}
): CommonOpts<TContext> {
  return {
    schemaComposer,
    getOrCreateOTC: (typeName, cfgOrThunk) => {
      return schemaComposer.getOrSet(typeName, () => {
        const tc = schemaComposer.createObjectTC(
          isFunction(cfgOrThunk) ? (cfgOrThunk: any)() : cfgOrThunk
        );
        return tc;
      });
    },
    getOrCreateITC: (typeName, cfgOrThunk) => {
      return schemaComposer.getOrSet(typeName, () => {
        const tc = schemaComposer.createInputTC(
          isFunction(cfgOrThunk) ? (cfgOrThunk: any)() : cfgOrThunk
        );
        return tc;
      });
    },
    getOrCreateETC: (typeName, cfgOrThunk) => {
      return schemaComposer.getOrSet(typeName, () => {
        const tc = schemaComposer.createEnumTC(
          isFunction(cfgOrThunk) ? (cfgOrThunk: any)() : cfgOrThunk
        );
        return tc;
      });
    },
    ...opts,
  };
}

export function getTypeName(name: string, opts: any): string {
  return `${(opts && opts.prefix) || 'Elastic'}${name}${(opts && opts.postfix) || ''}`;
}

// Remove newline multiline in descriptions
export function desc(str: string): string {
  return str.replace(/\n\s+/gi, ' ').replace(/^\s+/, '');
}

export function reorderKeys<T: Object>(obj: T, names: string[]): T {
  const orderedFields = {};
  const fields = { ...obj };
  names.forEach(name => {
    if (fields[name]) {
      orderedFields[name] = fields[name];
      delete fields[name];
    }
  });
  return { ...orderedFields, ...fields };
}

export type fetchElasticMappingOptsT = {
  elasticIndex: string,
  elasticType: string,
  elasticMapping: ElasticMappingT,
  elasticClient: Object,
};

export async function fetchElasticMapping(
  opts: fetchElasticMappingOptsT
): Promise<ElasticMappingT> {
  if (!opts.elasticIndex || typeof opts.elasticIndex !== 'string') {
    throw new Error('Must provide `elasticIndex` string parameter from your Elastic server.');
  }

  if (!opts.elasticType || typeof opts.elasticType !== 'string') {
    throw new Error('Must provide `elasticType` string parameter from your Elastic server.');
  }

  if (!opts.elasticClient) {
    throw new Error(
      'Must provide `elasticClient` Object parameter connected to your Elastic server.'
    );
  }

  const elasticMapping = (await opts.elasticClient.indices.getMapping({
    index: opts.elasticIndex,
    type: opts.elasticType,
  }))[opts.elasticIndex].mappings[opts.elasticType];

  return elasticMapping;
}
<|endoftext|>


<commit_before>// reduce and expand
export const reduce = (x, start, end) => (x - start) / (end - start);
export const expand = (x, start, end) => (x * (end - start)) + start;

export const chainFns = fns => value => {
  fns.forEach(fn => (value = fn(value)));
  return value;
};

export const noOp = () => {};

export const on = (event, fn) => {
  const listener = (...args) => fn(...args);

  global.window.addEventListener(event, listener);
  return () => global.window.removeEventListener(event, listener);
};

export const Range = initial => {
  const range = initial ? [initial, initial] : [];
  let empty = initial === undefined;

  range.extend = value => {
    if(empty) {
      range.push(value, value);
      empty = false;
      return;
    }

    if(value < range[0])
      range[0] = value;
    if(value > range[1])
      range[1] = value;
  };

  range.min = () => range[0];
  range.max = () => range[1];
  range.width = () => range[1] - range[0];

  return range;
};
<commit_msg>Fix  to take an optional target<commit_after>// reduce and expand
export const reduce = (x, start, end) => (x - start) / (end - start);
export const expand = (x, start, end) => (x * (end - start)) + start;

export const chainFns = fns => value => {
  fns.forEach(fn => (value = fn(value)));
  return value;
};

export const noOp = () => {};

export const on = (...args) => {
  let target = global.window;
  if(args.length > 2)
    target = args.shift();

  const [event, fn] = args;
  const listener = (...args) => fn(...args);

  target.addEventListener(event, listener);
  return () => target.removeEventListener(event, listener);
};

export const Range = initial => {
  const range = initial ? [initial, initial] : [];
  let empty = initial === undefined;

  range.extend = value => {
    if(empty) {
      range.push(value, value);
      empty = false;
      return;
    }

    if(value < range[0])
      range[0] = value;
    if(value > range[1])
      range[1] = value;
  };

  range.min = () => range[0];
  range.max = () => range[1];
  range.width = () => range[1] - range[0];

  return range;
};
<|endoftext|>


<commit_before>'use strict'

const { parse } = require('babylon')
const set = require('set-options')

const DEFAULT_BABYLON_OPTIONS = {
  allowImportExportEverywhere: true,
  allowReturnOutsideFunction: true,
  sourceType: 'module'
}

// @public
exports.astFromSource = (code, options = {}) => {
  options = set(options, DEFAULT_BABYLON_OPTIONS)
  return parse(code, options)
}

exports.throw = function (enable, message) {
  if (enable) {
    throw new Error(message)
  }
}

const REGEX_EXT = /\.([a-z0-9]+)$/i

// @returns {Boolean}
exports.matchExt = function (path, ext) {
  let match = path.match(REGEX_EXT)
  return match
    ? match[1] === ext
    // if there is no extension
    : true
}
<commit_msg>utils: adds util method to print code<commit_after>'use strict'

const { parse } = require('babylon')
const set = require('set-options')
const code = require('print-code')

const DEFAULT_BABYLON_OPTIONS = {
  allowImportExportEverywhere: true,
  allowReturnOutsideFunction: true,
  sourceType: 'module'
}

// Print the code of the error slice
exports.printCode = function (content, loc) {
  var gen = code(content)
    .highlight(loc.line)
    .slice(Math.max(0, loc.line - 2), loc.line + 2)

  if (typeof loc.column === 'number') {
    gen.arrow_mark(loc.line, loc.column)
  }

  return gen.get()
}

// @public
exports.astFromSource = (code, options = {}) => {
  options = set(options, DEFAULT_BABYLON_OPTIONS)
  return parse(code, options)
}

exports.throw = function (enable, message) {
  if (enable) {
    throw new Error(message)
  }
}

const REGEX_EXT = /\.([a-z0-9]+)$/i

// @returns {Boolean}
exports.matchExt = function (path, ext) {
  let match = path.match(REGEX_EXT)
  return match
    ? match[1] === ext
    // if there is no extension
    : true
}
<|endoftext|>


<commit_before>/**
 * @namespace Lyria
 * Lyria namespace decleration
 */
define('lyria/utils', ['jquery'], function($) {

  var Utils = {};

  /**
   *
   * @param {Object} filename
   *
   * @returns {Boolean}
   */
  Utils.isFile = function(filename) {
    var sepPos = filename.indexOf('.');
    if (sepPos === -1) {
      return false;
    }

    var filenameLength = filename.length;
    var diff = filenameLength - sepPos;

    // A filename extension is allowed to be one to four characters long.
    if ((diff > 1) && (diff <= 5)) {
      return true;
    } else {
      return false;
    }
  };
  /**
   *
   * @param {Object} anyObject
   *
   * @returns {Object}
   */
  Utils.cloneObject = function(anyObject) {
    return $.extend(true, {}, anyObject);
  };

  /**
   *
   * @param {Object} anyObject
   *
   * @returns {String}
   */
  Utils.serializeObject = function(anyObject) {
    if ((typeof anyObject !== 'object') || (anyObject instanceof $)) {
      return;
    }

      var str = '{';

      for (var p in anyObject) {
          if (anyObject.hasOwnProperty(p)) {
            if (anyObject[p] instanceof $) {
              continue;
            }

            var objKeys = Object.keys(anyObject);
            var commaStr = (objKeys.indexOf(p) === (objKeys.length - 1)) ? '' : ',';

            switch (typeof anyObject[p]) {
              case 'object': {
                str += p + ': ' + Utils.serializeObject(anyObject[p]) + commaStr + '\n';
              }
                break;
              case 'string': {
                str += p + ': "' + anyObject[p] + '"' + commaStr + '\n';
              }
                break;
              default: {
                str += p + ': ' + anyObject[p] + commaStr + '\n';
              }
                break;
            }
          }
      }
      str += '}';

      return str;
  };

  return Utils;

});
<commit_msg>Removed Utils.cloneObject as there is already the clone module<commit_after>/**
 * @namespace Lyria
 * Lyria namespace decleration
 */
define('lyria/utils', ['jquery'], function($) {

  var Utils = {};

  /**
   *
   * @param {Object} filename
   *
   * @returns {Boolean}
   */
  Utils.isFile = function(filename) {
    var sepPos = filename.indexOf('.');
    if (sepPos === -1) {
      return false;
    }

    var filenameLength = filename.length;
    var diff = filenameLength - sepPos;

    // A filename extension is allowed to be one to four characters long.
    if ((diff > 1) && (diff <= 5)) {
      return true;
    } else {
      return false;
    }
  };

  /**
   *
   * @param {Object} anyObject
   *
   * @returns {String}
   */
  Utils.serializeObject = function(anyObject) {
    if ((typeof anyObject !== 'object') || (anyObject instanceof $)) {
      return;
    }

      var str = '{';

      for (var p in anyObject) {
          if (anyObject.hasOwnProperty(p)) {
            if (anyObject[p] instanceof $) {
              continue;
            }

            var objKeys = Object.keys(anyObject);
            var commaStr = (objKeys.indexOf(p) === (objKeys.length - 1)) ? '' : ',';

            switch (typeof anyObject[p]) {
              case 'object': {
                str += p + ': ' + Utils.serializeObject(anyObject[p]) + commaStr + '\n';
              }
                break;
              case 'string': {
                str += p + ': "' + anyObject[p] + '"' + commaStr + '\n';
              }
                break;
              default: {
                str += p + ': ' + anyObject[p] + commaStr + '\n';
              }
                break;
            }
          }
      }
      str += '}';

      return str;
  };

  return Utils;

});
<|endoftext|>


<commit_before>import { easeOutQuint } from './easing'

export const includes = (val, arr) => arr.includes ? arr.includes(val) : !!arr.filter((item) => item === val).length
export const values = Object.values || ((obj) => Object.keys(obj).map((key) => obj[key]))
export const compose = (...fns) => (val) => fns.reduceRight((currVal, fn) => fn(currVal), val)
export const minMap = (...vals) => (val) => Math.min(...vals, val)
export const maxMap = (...vals) => (val) => Math.max(...vals, val)
export const noop = () => {}
export const on = (evt, opts = false) => (cb) => (el) => {
  el.addEventListener(evt, cb, opts)
  return () => el.removeEventListener(evt, cb)
}

export const onWindowScroll = (cb) => on('scroll', true)(cb)(window)

export const onScroll = (cb, { target = window } = {}) =>
  onWindowScroll((e) => (target === window || target === e.target) && cb(e))

export const onScrollEnd = (cb, { wait = 100, target = window } = {}) => ((timeoutID) => onScroll((evt) => {
  clearTimeout(timeoutID)
  timeoutID = setTimeout(() => evt.target === target ? cb() : undefined, wait)
}))(0)

export const onScrollStart = (cb, { target = window } = {}) => {
  let started = false
  const offScrollEnd = onScrollEnd(() => { started = false }, { target })
  const offScroll = onScroll((e) => {
    if (!started) {
      started = true
      cb(e)
    }
  }, { target })

  return () => {
    offScroll()
    offScrollEnd()
  }
}

export const onSwipe = (cb) => (target) => {
  const offTouchStart = on('touchstart')(({ targetTouches }) => {
    const { pageX: startX, pageY: startY } = targetTouches[0]
    const offTouchEnd = on('touchend')(({ changedTouches }) => {
      const { pageX: endX, pageY: endY } = changedTouches[0]
      const xDiff = endX - startX
      const absXDiff = Math.abs(xDiff)
      const yDiff = endY - startY
      const absYDiff = Math.abs(yDiff)
      if (Math.max(absXDiff, absYDiff) > 20) {
        const dir = absXDiff > absYDiff ? (/* h */ xDiff < 0 ? 'right' : 'left') : (/* v */ yDiff < 0 ? 'down' : 'up')
        cb(dir)
      }
      offTouchEnd()
    })(target)
  })(target)

  return offTouchStart
}

export const trackTouchesForElement = (el) => {
  let touchIds = []
  on('touchend')(({ targetTouches }) => { touchIds = targetTouches })(el)
  return () => touchIds.length
}

export const trackOngoingMouseInteraction = (el) => {
  let isInteracting = false
  on('mousedown')(() => { isInteracting = true })(el)
  on('mouseup')(() => { isInteracting = false })(document.body)
  return () => isInteracting
}

export const hasOngoingInteraction = (el) => {
  const getOngoingTouchCount = trackTouchesForElement(el)
  const getOngoingMouseClick = trackOngoingMouseInteraction(el)
  return () => getOngoingTouchCount() || getOngoingMouseClick()
}

export const isWhollyInView = (parent) => (child = { getBoundingClientRect: () => ({}) }) => {
  const { left: cLeft, right: cRight } = child.getBoundingClientRect()
  const { left: pLeft, right: pRight } = parent.getBoundingClientRect()
  return (cLeft >= pLeft && cRight <= pRight)
}

export const animate = (el, {
  delta = 0,
  immediate = false,
  duration = 500,
  easing = easeOutQuint,
  originalOverflowX = 'auto',
  prop = 'scrollTop'
} = {}) => (new Promise((res, rej) => {
  if (!delta) return res()
  const initialVal = el[prop]
  if (immediate) {
    el[prop] = initialVal + delta
    return res()
  }
  let hasBailed = false
  const bail = () => {
    hasBailed = true
    const pos = el[prop]
    el.removeEventListener('touchstart', bail)
    el.style.overflowX = originalOverflowX
    el[prop] = pos
    return rej('Animation interupted by interaction')
  }
  el.addEventListener('touchstart', bail)
  let startTime = null
  const step = (timestamp) => {
    if (hasBailed) return
    if (!startTime) startTime = timestamp
    const progressTime = timestamp - startTime
    const progressRatio = easing(progressTime / duration)
    el[prop] = initialVal + (delta * progressRatio)
    if (progressTime < duration) {
      window.requestAnimationFrame(step)
    } else {
      el[prop] = initialVal + delta // jump to end when animation is complete. necessary at least for immediate scroll
      res()
    }
  }
  // We are going to temporarily prevent the user from being able to scroll during the animation.
  // This will prevent a janky fight between user scroll and animation which is just bad user experience.
  // el.style.overflowX = 'hidden'
  window.requestAnimationFrame(step)
})).then(() => setTimeout(() => {
  // Firefox doesn't like when this is done immediatly after jumping to the end.
  // Setting overflow somehow triggers a scroll event throwing this whole thing into an infinite loop.
  // Kicking to the next tick solves this.

  // Give scroll control back to the user once animation is done.
  el.style.overflowX = originalOverflowX
}, 0))
<commit_msg>another attempt to fix locked track scroll<commit_after>import { easeOutQuint } from './easing'

export const includes = (val, arr) => arr.includes ? arr.includes(val) : !!arr.filter((item) => item === val).length
export const values = Object.values || ((obj) => Object.keys(obj).map((key) => obj[key]))
export const compose = (...fns) => (val) => fns.reduceRight((currVal, fn) => fn(currVal), val)
export const minMap = (...vals) => (val) => Math.min(...vals, val)
export const maxMap = (...vals) => (val) => Math.max(...vals, val)
export const noop = () => {}
export const on = (evt, opts = false) => (cb) => (el) => {
  el.addEventListener(evt, cb, opts)
  return () => el.removeEventListener(evt, cb)
}

export const onWindowScroll = (cb) => on('scroll', true)(cb)(window)

export const onScroll = (cb, { target = window } = {}) =>
  onWindowScroll((e) => (target === window || target === e.target) && cb(e))

export const onScrollEnd = (cb, { wait = 100, target = window } = {}) => ((timeoutID) => onScroll((evt) => {
  clearTimeout(timeoutID)
  timeoutID = setTimeout(() => evt.target === target ? cb() : undefined, wait)
}))(0)

export const onScrollStart = (cb, { target = window } = {}) => {
  let started = false
  const offScrollEnd = onScrollEnd(() => { started = false }, { target })
  const offScroll = onScroll((e) => {
    if (!started) {
      started = true
      cb(e)
    }
  }, { target })

  return () => {
    offScroll()
    offScrollEnd()
  }
}

export const onSwipe = (cb) => (target) => {
  const offTouchStart = on('touchstart')(({ targetTouches }) => {
    const { pageX: startX, pageY: startY } = targetTouches[0]
    const offTouchEnd = on('touchend')(({ changedTouches }) => {
      const { pageX: endX, pageY: endY } = changedTouches[0]
      const xDiff = endX - startX
      const absXDiff = Math.abs(xDiff)
      const yDiff = endY - startY
      const absYDiff = Math.abs(yDiff)
      if (Math.max(absXDiff, absYDiff) > 20) {
        const dir = absXDiff > absYDiff ? (/* h */ xDiff < 0 ? 'right' : 'left') : (/* v */ yDiff < 0 ? 'down' : 'up')
        cb(dir)
      }
      offTouchEnd()
    })(target)
  })(target)

  return offTouchStart
}

export const trackTouchesForElement = (el) => {
  let touchIds = []
  on('touchend')(({ targetTouches }) => { touchIds = targetTouches })(el)
  return () => touchIds.length
}

export const trackOngoingMouseInteraction = (el) => {
  let isInteracting = false
  on('mousedown')(() => { isInteracting = true })(el)
  on('mouseup')(() => { isInteracting = false })(document.body)
  return () => isInteracting
}

export const hasOngoingInteraction = (el) => {
  const getOngoingTouchCount = trackTouchesForElement(el)
  const getOngoingMouseClick = trackOngoingMouseInteraction(el)
  return () => getOngoingTouchCount() || getOngoingMouseClick()
}

export const isWhollyInView = (parent) => (child = { getBoundingClientRect: () => ({}) }) => {
  const { left: cLeft, right: cRight } = child.getBoundingClientRect()
  const { left: pLeft, right: pRight } = parent.getBoundingClientRect()
  return (cLeft >= pLeft && cRight <= pRight)
}

export const animate = (el, {
  delta = 0,
  immediate = false,
  duration = 500,
  easing = easeOutQuint,
  prop = 'scrollTop'
} = {}) => (new Promise((res, rej) => {
  if (!delta) return res()
  const initialVal = el[prop]
  if (immediate) {
    el[prop] = initialVal + delta
    return res()
  }
  let hasBailed = false
  const bail = () => {
    hasBailed = true
    const pos = el[prop]
    el.removeEventListener('touchstart', bail)
    el[prop] = pos
    return rej('Animation interupted by interaction')
  }
  el.addEventListener('touchstart', bail)
  let startTime = null
  const step = (timestamp) => {
    if (hasBailed) return
    if (!startTime) startTime = timestamp
    const progressTime = timestamp - startTime
    const progressRatio = easing(progressTime / duration)
    el[prop] = initialVal + (delta * progressRatio)
    if (progressTime < duration) {
      window.requestAnimationFrame(step)
    } else {
      el[prop] = initialVal + delta // jump to end when animation is complete. necessary at least for immediate scroll
      res()
    }
  }
  window.requestAnimationFrame(step)
}))
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import MomentPropType from 'react-moment-propTypes';
import moment from 'moment';

import config from './config.js';
import classes from './classes.js';

import {
    makeInterval,
    getTotalWeeksInMonth,
    getFirstDayOfFirstWeek
} from './utils.js';

import {
    getYearsInterval
} from './utils.js';

const View = ViewType => class extends Component {
    static propTypes = {
        onDateClick: PropTypes.func.isRequired,
        date: MomentPropType.momentObj
    };

    static defaultProps = {
        date: new Date()
    };

    constructor(props) {
        super(props);

        this.handleOnDateClick = this.handleOnDateClick.bind(this);
    }

    handleOnDateClick(date) {
        this.props.onDateClick(date);
    }

    render() {
        return <ViewType date={ this.props.date } handleOnDateClick={ this.handleOnDateClick } />
    }
};

const Weeks = (props) => {
    const { date } = props;
    const rows = getTotalWeeksInMonth(date);
    const now = moment();
    const selected = moment(date);
    const weekdays = makeInterval(config.weeksCols)
        .map((_, i) => moment().weekday(i).format('dd'));

    const fdow = getFirstDayOfFirstWeek(date);

    return (

                { weekdays.map((weekday, i) =>

                        { weekday }

                ) }

            { makeInterval(rows).map(
                (_, i) =>

                { weekdays.map((_, j) => {
                    const next = moment( fdow ).add(i + j + 6 * i, 'day');
                    return (

 props.handleOnDateClick(moment( next )) }
                            className={
                                classes.weeksCell +
                                ( next.isSame(now, 'day') ? ` ${ classes.current }` : '' ) +
                                ( next.isSame(selected, 'day') ? ` ${ classes.selected }` : '' ) +
                                ( next.isSame(date, 'month') ? '' : ` ${ classes.weeksCellNotCurMonth }` )
                            }>
                            { next.format('D') }

                    );
                }
                ) }

            ) }

    );
}

const Months = (props) => {
    const { date } = props;
    const monthFrom = moment(date).month(0);
    const format = 'MMM';
    const rows = 12 / config.monthsCols;
    const now = moment();
    const selected = moment(date);

    return (

        { makeInterval(rows).map((_, i) =>

                { makeInterval(config.monthsCols).map( (_, j) => {
                    const next = moment( monthFrom ).add(i + j + ( config.monthsCols - 1 ) * i, 'month');
                    return (

 props.handleOnDateClick(moment( next )) }
                            className={
                                classes.monthsCell +
                                ( next.isSame(selected, 'day') ? ` ${ classes.selected }` : '' ) +
                                ( next.isSame(now, 'day') ? ` ${ classes.current }` : '' )
                            }
                            >
                            { next.format(format) }

                    )
                }) }

        ) }

    );
}

const Years = (props) => {
    const { date } = props;
    const { yearsFrom } = getYearsInterval(date, config.yearsInterval);
    const format = 'YYYY';
    const rows = ( config.yearsInterval * 2 + 1 ) / config.yearsCols;
    const now = moment();
    const selected = moment(date);

    return (

        { makeInterval(rows).map((_, i) =>

                { makeInterval(config.yearsCols).map( (_, j) => {
                    const next = moment( yearsFrom ).add(i + j + ( config.yearsCols - 1 ) * i, 'year');
                    return (

 props.handleOnDateClick(moment( next )) }
                            className={
                                classes.yearsCell +
                                ( next.isSame(selected, 'day') ? ` ${ classes.selected }` : '' ) +
                                ( next.isSame(now, 'day') ? ` ${ classes.current }` : '' )
                            }
                            >
                            { next.format(format) }

                    )
                }) }

        ) }

    );
}

export const WeeksView  = View(Weeks);
export const MonthsView = View(Months);
export const YearsView  = View(Years);
<commit_msg>Fixed incorrect letter case in import<commit_after>import React, { Component, PropTypes } from 'react';
import MomentPropType from 'react-moment-proptypes';
import moment from 'moment';

import config from './config.js';
import classes from './classes.js';

import {
    makeInterval,
    getTotalWeeksInMonth,
    getFirstDayOfFirstWeek
} from './utils.js';

import {
    getYearsInterval
} from './utils.js';

const View = ViewType => class extends Component {
    static propTypes = {
        onDateClick: PropTypes.func.isRequired,
        date: MomentPropType.momentObj
    };

    static defaultProps = {
        date: new Date()
    };

    constructor(props) {
        super(props);

        this.handleOnDateClick = this.handleOnDateClick.bind(this);
    }

    handleOnDateClick(date) {
        this.props.onDateClick(date);
    }

    render() {
        return <ViewType date={ this.props.date } handleOnDateClick={ this.handleOnDateClick } />
    }
};

const Weeks = (props) => {
    const { date } = props;
    const rows = getTotalWeeksInMonth(date);
    const now = moment();
    const selected = moment(date);
    const weekdays = makeInterval(config.weeksCols)
        .map((_, i) => moment().weekday(i).format('dd'));

    const fdow = getFirstDayOfFirstWeek(date);

    return (

                { weekdays.map((weekday, i) =>

                        { weekday }

                ) }

            { makeInterval(rows).map(
                (_, i) =>

                { weekdays.map((_, j) => {
                    const next = moment( fdow ).add(i + j + 6 * i, 'day');
                    return (

 props.handleOnDateClick(moment( next )) }
                            className={
                                classes.weeksCell +
                                ( next.isSame(now, 'day') ? ` ${ classes.current }` : '' ) +
                                ( next.isSame(selected, 'day') ? ` ${ classes.selected }` : '' ) +
                                ( next.isSame(date, 'month') ? '' : ` ${ classes.weeksCellNotCurMonth }` )
                            }>
                            { next.format('D') }

                    );
                }
                ) }

            ) }

    );
}

const Months = (props) => {
    const { date } = props;
    const monthFrom = moment(date).month(0);
    const format = 'MMM';
    const rows = 12 / config.monthsCols;
    const now = moment();
    const selected = moment(date);

    return (

        { makeInterval(rows).map((_, i) =>

                { makeInterval(config.monthsCols).map( (_, j) => {
                    const next = moment( monthFrom ).add(i + j + ( config.monthsCols - 1 ) * i, 'month');
                    return (

 props.handleOnDateClick(moment( next )) }
                            className={
                                classes.monthsCell +
                                ( next.isSame(selected, 'day') ? ` ${ classes.selected }` : '' ) +
                                ( next.isSame(now, 'day') ? ` ${ classes.current }` : '' )
                            }
                            >
                            { next.format(format) }

                    )
                }) }

        ) }

    );
}

const Years = (props) => {
    const { date } = props;
    const { yearsFrom } = getYearsInterval(date, config.yearsInterval);
    const format = 'YYYY';
    const rows = ( config.yearsInterval * 2 + 1 ) / config.yearsCols;
    const now = moment();
    const selected = moment(date);

    return (

        { makeInterval(rows).map((_, i) =>

                { makeInterval(config.yearsCols).map( (_, j) => {
                    const next = moment( yearsFrom ).add(i + j + ( config.yearsCols - 1 ) * i, 'year');
                    return (

 props.handleOnDateClick(moment( next )) }
                            className={
                                classes.yearsCell +
                                ( next.isSame(selected, 'day') ? ` ${ classes.selected }` : '' ) +
                                ( next.isSame(now, 'day') ? ` ${ classes.current }` : '' )
                            }
                            >
                            { next.format(format) }

                    )
                }) }

        ) }

    );
}

export const WeeksView  = View(Weeks);
export const MonthsView = View(Months);
export const YearsView  = View(Years);
<|endoftext|>


<commit_before>// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// Based on code created by Jules Gravinese (http://www.webveteran.com/)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/

Sound = {
  tracks: {},
  _enabled: true,
  template:
    new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
  enable: function(){
    Sound._enabled = true;
  },
  disable: function(){
    Sound._enabled = false;
  },
  play: function(url){
    if(!Sound._enabled) return;
    var options = Object.extend({
      track: 'global', url: url, replace: false
    }, arguments[1] || {});

    if(options.replace && this.tracks[options.track]) {
      $R(0, this.tracks[options.track].id).each(function(id){
        var sound = $('sound_'+options.track+'_'+id);
        sound.Stop && sound.Stop();
        sound.remove();
      })
      this.tracks[options.track] = null;
    }

    if(!this.tracks[options.track])
      this.tracks[options.track] = { id: 0 }
    else
      this.tracks[options.track].id++;

    options.id = this.tracks[options.track].id;
    if (Prototype.Browser.IE)
      $$('body')[0].insert(new Element('bgsound',{
        id: 'sound_'+options.track+'_'+options.id,
        src: options.url, loop: 1, autostart: true
      }));
    else
      $$('body')[0].insert(Sound.template.evaluate(options));
  }
};

if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
  if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
    Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
  else
    Sound.play = function(){}
}
<commit_msg>Save a few additional lines<commit_after>// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// Based on code created by Jules Gravinese (http://www.webveteran.com/)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/

Sound = {
  tracks: {},
  _enabled: true,
  template:
    new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
  enable: function(){
    Sound._enabled = true;
  },
  disable: function(){
    Sound._enabled = false;
  },
  play: function(url){
    if(!Sound._enabled) return;
    var options = Object.extend({
      track: 'global', url: url, replace: false
    }, arguments[1] || {});

    if(options.replace && this.tracks[options.track]) {
      $R(0, this.tracks[options.track].id).each(function(id){
        var sound = $('sound_'+options.track+'_'+id);
        sound.Stop && sound.Stop();
        sound.remove();
      })
      this.tracks[options.track] = null;
    }

    if(!this.tracks[options.track])
      this.tracks[options.track] = { id: 0 }
    else
      this.tracks[options.track].id++;

    options.id = this.tracks[options.track].id;
    $$('body')[0].insert(
      Prototype.Browser.IE ? new Element('bgsound',{
        id: 'sound_'+options.track+'_'+options.id,
        src: options.url, loop: 1, autostart: true
      }) : Sound.template.evaluate(options));
  }
};

if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
  if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
    Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>')
  else
    Sound.play = function(){}
}
<|endoftext|>


<commit_before>import {default as stringify} from "./stringify";
import {default as combiningMarks} from "./combiningMarks";
import {merge} from "d3-array";

const splitChars = ["-",  "/",  ";",  ":",  "&",
                    "u0E2F",  // thai character pairannoi
                    "u0EAF",  // lao ellipsis
                    "u0ECC",  // lao cancellation mark
                    "u0EC6",  // lao ko la (word repetition)
                    "u104A",  // myanmar sign little section
                    "u104B",  // myanmar sign section
                    "u104C",  // myanmar symbol locative
                    "u104D",  // myanmar symbol completed
                    "u104E",  // myanmar symbol aforementioned
                    "u104F",  // myanmar symbol genitive
                    "u2013",  // en dash
                    "u2014",  // em dash
                    "u2027",  // simplified chinese hyphenation point
                    "u3000",  // simplified chinese ideographic space
                    "u3001",  // simplified chinese ideographic comma
                    "u3002",  // simplified chinese ideographic full stop
                    "uFF5E"  // wave dash
                  ];

const prefixChars = ["'",  "<",  "(",  "{",  "[",
                     "u00AB",  // left-pointing double angle quotation mark
                     "u300A",  // left double angle bracket
                     "u3008"  // left angle bracket
                   ];

const suffixChars = ["'",  ">",  ")",  "}",  "]",  ".",  "!",  "?",
                     "u00BB",  // right-pointing double angle quotation mark
                     "u300B",  // right double angle bracket
                     "u3009"  // right angle bracket
                   ].concat(splitChars);

const burmeseRange = "\u1000-\u102A\u103F-\u1049\u1050-\u1055";
const japaneseRange = "\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u3400-\u4dbf";
const chineseRange = "\u3400-\u9FBF";
const laoRange = "\u0E80-\u0EFF";

const noSpaceRange = burmeseRange + chineseRange + laoRange;

const splitWords = new RegExp(`[^\\s|\\${splitChars.join("|\\")}]+(\\${splitChars.join("|\\")})*`, "g");
const japaneseChars = new RegExp(`[${japaneseRange}]`);
const noSpaceLanguage = new RegExp(`[${noSpaceRange}]`);
const splitAllChars = new RegExp(`(\\${prefixChars.join("|\\")})*[${noSpaceRange}]|[a-z0-9]+(\\${suffixChars.join("|\\")}|\\${combiningMarks.join("|\\")})*`, "gi");

/**
    @function width
    @desc Splits a given sentence into an array of words.
    @param {String} sentence
*/
export default function(sentence) {
  if (!noSpaceLanguage.test(sentence)) return stringify(sentence).match(splitWords);
  return merge(stringify(sentence).match(splitWords).map((d) => {
    if (!japaneseChars.test(d) && noSpaceLanguage.test(d)) return d.match(splitAllChars);
    return [d];
  }));
}

export {prefixChars, splitChars, splitWords, suffixChars};
<commit_msg>fixes split bug with suffix and combining marks<commit_after>import {default as stringify} from "./stringify";
import {default as combiningMarks} from "./combiningMarks";
import {merge} from "d3-array";

const splitChars = ["-",  "/",  ";",  ":",  "&",
                    "u0E2F",  // thai character pairannoi
                    "u0EAF",  // lao ellipsis
                    "u0ECC",  // lao cancellation mark
                    "u0EC6",  // lao ko la (word repetition)
                    "u104A",  // myanmar sign little section
                    "u104B",  // myanmar sign section
                    "u104C",  // myanmar symbol locative
                    "u104D",  // myanmar symbol completed
                    "u104E",  // myanmar symbol aforementioned
                    "u104F",  // myanmar symbol genitive
                    "u2013",  // en dash
                    "u2014",  // em dash
                    "u2027",  // simplified chinese hyphenation point
                    "u3000",  // simplified chinese ideographic space
                    "u3001",  // simplified chinese ideographic comma
                    "u3002",  // simplified chinese ideographic full stop
                    "uFF5E"  // wave dash
                  ];

const prefixChars = ["'",  "<",  "(",  "{",  "[",
                     "u00AB",  // left-pointing double angle quotation mark
                     "u300A",  // left double angle bracket
                     "u3008"  // left angle bracket
                   ];

const suffixChars = ["'",  ">",  ")",  "}",  "]",  ".",  "!",  "?",
                     "u00BB",  // right-pointing double angle quotation mark
                     "u300B",  // right double angle bracket
                     "u3009"  // right angle bracket
                   ].concat(splitChars);

const burmeseRange = "\u1000-\u102A\u103F-\u1049\u1050-\u1055";
const japaneseRange = "\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u3400-\u4dbf";
const chineseRange = "\u3400-\u9FBF";
const laoRange = "\u0E80-\u0EFF";

const noSpaceRange = burmeseRange + chineseRange + laoRange;

const splitWords = new RegExp(`[^\\s|\\${splitChars.join("|\\")}]+(\\${splitChars.join("|\\")})*`, "g");
const japaneseChars = new RegExp(`[${japaneseRange}]`);
const noSpaceLanguage = new RegExp(`[${noSpaceRange}]`);
const splitAllChars = new RegExp(`(\\${prefixChars.join("|\\")})*[${noSpaceRange}](\\${suffixChars.join("|\\")}|\\${combiningMarks.join("|\\")})*|[a-z0-9]+`, "gi");

/**
    @function width
    @desc Splits a given sentence into an array of words.
    @param {String} sentence
*/
export default function(sentence) {
  if (!noSpaceLanguage.test(sentence)) return stringify(sentence).match(splitWords);
  return merge(stringify(sentence).match(splitWords).map((d) => {
    if (!japaneseChars.test(d) && noSpaceLanguage.test(d)) return d.match(splitAllChars);
    return [d];
  }));
}

export {prefixChars, splitChars, splitWords, suffixChars};
<|endoftext|>