<commit_before>////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////Builds the HTML Table from ElectionIDs

function buildElectionTable(res) {

	 var electionConf = JSON.parse(electionConfigRaw);
	 var elections = electionConf.elections;

	 var lastMix = "http://localhost:"+electionConf["nginx-port"];
	 //don't use port 80 if it's not deployed
	 if(electionConf.deployment === true){
		 var sAddresses = JSON.parse(sAddressesRaw);
		 lastMix = sAddresses["server-address"].mix2;
	 }

	 document.getElementById("elections").innerHTML = "";

	 var head$ = $('
');
	 head$.append($('').html(" Election IDs "));
	 head$.append($('').html(" Election Title "));
	 head$.append($('').html(" Starting Time "));
	 head$.append($('').html(" Ending Time "));
	 head$.append($('').html(" Election State "));
  $("#elections").append(head$);

  for (var i = 0 ; i < elections.length ; i++) {
 	 var elecID = elections[i].electionID;
 	 var elecStatus = 'waiting';

      var row$ = $('
');

      row$.append($('').html("   "+elections[i].electionID+"    "));
      row$.append($('').html("   "+elections[i].electionTitle+"   "));
      row$.append($('').html("   "+elections[i].startTime.substring(0, elections[i].startTime.length-9)+"   "));
      row$.append($('').html("   "+elections[i].endTime.substring(0, elections[i].endTime.length-9)+"   "));
      row$.append($('').html("   "+elecStatus+"   "));
      $("#elections").append(row$);

      getElectionStatus(elecID, function (eleID, stat){
 		 document.getElementById(eleID).innerHTML = stat;
 	 });
  }

  function getElectionStatus(eleID, callback) {
      // Detemine the status of the system: (not-yet) open/closed,
      // by quering the final mix server.
      // Depending on the state, either the voting tab or the
      // verification tab will be opened.
      //
      // The state is detemined in a (too?) simple way, by
      // checking if the final server has ready result.
      //
 	 var stat = 'what';
 	 var url = lastMix+'/'+eleID+'/mix/03/status';
      $.get(url)
       .fail(function () {
          var stat = 'no response';
          callback(eleID, stat)
        })
       .done(function (result) {  // we have some response
          var stat = 'pending';
     	 if (result.status==='result ready'){
         	 stat = 'closed';
          }
          else {
         	 stat = 'open';
          }
          callback(eleID, stat)
        });

  }

  ////////////////////////////////////////////////////////////////
  ///////// Refresh State

	/* Refresh */
  var electionStates = window.setInterval(function() {
 	 for (var i = 0 ; i < elections.length ; i++) {
     	 var elecID = elections[i].electionID;
     	 getElectionStatus(elecID, function (eleID, stat){
     		 document.getElementById(eleID).innerHTML = stat;
     	 });
 	 }
  }, 1000);

  $('#welcome').show();

  res(electionStates);

}
<commit_msg>escaping HTML and displaying browser time for elections<commit_after>////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////Builds the HTML Table from ElectionIDs

function buildElectionTable(res) {

	// expected time format is 'yy.mm.dd h:min [options not used yet]' in UTC+000
	var resolveTime = function(time){
	    var dateTime = time.split(" ");
	    var date = dateTime[0].split(".");
	    var clientDate = new Date(date[0]+"-"+date[1]+"-"+date[2]+"T"+dateTime[1]);
	    clientDate = new Date(clientDate.setTime(clientDate.getTime()-clientDate.getTimezoneOffset()*60000))

		var month = clientDate.getMonth()+1<10 ? "0"+(clientDate.getMonth()+1) : (clientDate.getMonth()+1);
		var day = clientDate.getDate()+1<10 ? "0"+clientDate.getDate() : clientDate.getDate();

		var hours = clientDate.getHours()
		var dt = (hours>=12)?"PM":"AM";
		hours = (hours%12==0)?12:(hours%12);

		date = clientDate.getFullYear()+"."+month+"."+day;
		time = hours+":"+clientDate.getMinutes()+" "+dt;
		dateTime = date + " " + time;

	    return dateTime;
	}

    //////////////////////////////////////////////////////////////////////////////
    /// Escape HTML
    var MAP = { '&': '&',
            '<': '<',
            '>': '>',
            '"': '"',
            "'": '''};

    function escapeHTML(s, forAttribute) {
    	return s.replace(forAttribute ? /[&<>'"]/g : /[&<>]/g, function(c) {
    		return MAP[c];
    	});
    }

    //////////////////////////////////////////////////////////////////////////////
    /// Build the election table
	var electionConf = JSON.parse(electionConfigRaw);
	var elections = electionConf.elections;

	var lastMix = "http://localhost:"+electionConf["nginx-port"];
	//don't use port 80 if it's not deployed
	if(electionConf.deployment === true){
		var sAddresses = JSON.parse(sAddressesRaw);
		lastMix = sAddresses["server-address"].mix2;
	}

	document.getElementById("elections").innerHTML = "";

	var head$ = $('
');
	head$.append($('').html(" Election IDs "));
	head$.append($('').html(" Election Title "));
	head$.append($('').html(" Starting Time "));
	head$.append($('').html(" Ending Time "));
	head$.append($('').html(" Election State "));
	$("#elections").append(head$);

	for (var i = 0 ; i < elections.length ; i++) {
		var elecID = elections[i].electionID;
		var elecStatus = 'waiting';
		var startingTime = resolveTime(elections[i].startTime)
		var endingTime = resolveTime(elections[i].endTime)
		var row$ = $('
');

		row$.append($('').html("   "+elections[i].electionID+"    "));
		row$.append($('').html("   "+escapeHTML(elections[i].electionTitle, true)+"   "));
		row$.append($('').html("   "+startingTime+"   "));
		row$.append($('').html("   "+endingTime+"   "));
		row$.append($('').html("   "+elecStatus+"   "));
		$("#elections").append(row$);

		getElectionStatus(elecID, function (eleID, stat){
			document.getElementById(eleID).innerHTML = stat;
		});

	}

  function getElectionStatus(eleID, callback) {
      // Detemine the status of the system: (not-yet) open/closed,
      // by quering the final mix server.
      // Depending on the state, either the voting tab or the
      // verification tab will be opened.
      //
      // The state is detemined in a (too?) simple way, by
      // checking if the final server has ready result.
      //
 	 var stat = 'what';
 	 var url = lastMix+'/'+eleID+'/mix/03/status';
      $.get(url)
       .fail(function () {
          var stat = 'no response';
          callback(eleID, stat)
        })
       .done(function (result) {  // we have some response
          var stat = 'pending';
     	 if (result.status==='result ready'){
         	 stat = 'closed';
          }
          else {
         	 stat = 'open';
          }
          callback(eleID, stat)
        });

  }

  // expected time format is 'yy.mm.dd h:min [options not used yet]' in UTC+000
  var resolveTime = function(time){
      var dateTime = time.split(" ");
      var date = dateTime[0].split(".");
      var clientDate = new Date(date[0]+"-"+date[1]+"-"+date[2]+"T"+dateTime[1]);
      clientDate = new Date(clientDate.setTime(clientDate.getTime()-clientDate.getTimezoneOffset()*60000))
      return clientDate;
  }

  ////////////////////////////////////////////////////////////////
  ///////// Refresh State

	/* Refresh */
  var electionStates = window.setInterval(function() {
 	 for (var i = 0 ; i < elections.length ; i++) {
     	 var elecID = elections[i].electionID;
     	 getElectionStatus(elecID, function (eleID, stat){
     		 document.getElementById(eleID).innerHTML = stat;
     	 });
 	 }
  }, 1000);

  $('#welcome').show();

  res(electionStates);

}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {
  Box,
  Icon,
  StatelessTextInput as Input,
  Row,
  Text,
  Button,
  Col,
} from '@tlon/indigo-react';

import * as bitcoin from 'bitcoinjs-lib';
import * as kg from 'urbit-key-generation';
import * as bip39 from 'bip39';

import Sent from './sent.js'

window.bitcoin = bitcoin;
window.kg = kg;
window.bip39 = bip39;

export default class Invoice extends Component {
  constructor(props) {
    super(props);

    this.state = {
      masterTicket: '',
      ready: false,
      sent: false,
    };

    this.checkTicket = this.checkTicket.bind(this);
    this.broadCastTx = this.broadCastTx.bind(this);
    this.sendBitcoin = this.sendBitcoin.bind(this);
  }

  broadCastTx(psbtHex) {
    let command = {
      'broadcast-tx': psbtHex
    }
    return this.props.api.btcWalletCommand(command)
  }

  sendBitcoin(ticket, psbt) {

    const mnemonic = kg.deriveNodeSeed(ticket, 'bitcoin');
    const seed = bip39.mnemonicToSeed(mnemonic);
    const hd = bitcoin.bip32.fromSeed(seed);

    const newPsbt = bitcoin.Psbt.fromBase64(psbt);

    const hex =
      newPsbt.data.inputs
             .reduce((psbt, input, idx) => {
               const path = input.bip32Derivation[0].path
               const prv = hd.derivePath(path).privateKey;
               return psbt.signInput(idx, bitcoin.ECPair.fromPrivateKey(prv));

             }, newPsbt)
             .finalizeAllInputs()
             .extractTransaction()
             .toHex();

    console.log({hex});
    this.broadCastTx(hex).then(res => this.setState({sent: true}));
  }

  checkTicket(e){
    // TODO: port over bridge ticket validation logic
    let masterTicket = e.target.value;
    let ready = (masterTicket.length > 0);
    this.setState({masterTicket, ready});
  }

  render() {
    const { stopSending, payee, denomination, denomAmount, satsAmount } = this.props;
    const { sent } = this.state;
    return (
      <>
        { sent ?
          <Sent
            payee={payee}
            denomination={denomination}
            denomAmount={denomAmount}
            satsAmount={satsAmount}
          /> :
          <Col
            height='400px'
            width='100%'
            backgroundColor='white'
            borderRadius='32px'
            mb={5}
            p={5}
          >
            <Row
              justifyContent='space-between'
              alignItems='center'
            >
              <Text bold fontSize={1}>Invoice</Text>
              <Icon
                icon='X'
                cursor='pointer'
                onClick={() => stopSending()}
              />
            </Row>
            <Box
              mt={4}
              backgroundColor='rgba(0, 159, 101, 0.05)'
              borderRadius='12px'
            >
              <Box
                padding={4}
              >
                <Row>
                  <Text fontWeight='500'>You are sending</Text>
                </Row>
                <Row
                  mt={2}
                >
                  <Text
                    color='green'
                  >{`$${denomAmount} ${denomination}`}</Text>
                  <Text
                    ml={2}
                    color='gray'
                  >{`${satsAmount} sats`}</Text>
                </Row>
                <Row
                  mt={2}
                >
                  <Text>To:</Text>
                  <Text
                    ml={2}
                  >{payee}</Text>
                </Row>
              </Box>
            </Box>
            <Box mt={3} mb={2}>
              <Text fontSize='14px' fontWeight='500'>
                Master Key
              </Text>
            </Box>
            <Input
              value={this.state.masterTicket}
              fontSize="14px"
              type="password"
              name="masterTicket"
              obscure={value => value.replace(/[^~-]+/g, '••••••')}
              placeholder="••••••-••••••-••••••-••••••"
              autoCapitalize="none"
              autoCorrect="off"
              onChange={this.checkTicket}
            />
            <Row
              flexDirection='row-reverse'
              mt={4}
            >
              <Button
                primary
                children='Send BTC'
                mr={3}
                fontSize={1}
                borderRadius='24px'
                py='24px'
                px='24px'
                onClick={() => this.sendBitcoin(this.state.masterTicket, store.state.psbt)}
                disabled={!this.state.ready}
                style={{cursor: this.state.ready ? "pointer" : "default"}}
              />
            </Row>
          </Col>
        }
      </>
    );
  }
}
<commit_msg>btc: styling improvements in invoice.js<commit_after>import React, { Component } from 'react';
import {
  Box,
  Icon,
  StatelessTextInput as Input,
  Row,
  Text,
  Button,
  Col,
} from '@tlon/indigo-react';

import * as bitcoin from 'bitcoinjs-lib';
import * as kg from 'urbit-key-generation';
import * as bip39 from 'bip39';

import Sent from './sent.js'

window.bitcoin = bitcoin;
window.kg = kg;
window.bip39 = bip39;

export default class Invoice extends Component {
  constructor(props) {
    super(props);

    this.state = {
      masterTicket: '',
      ready: false,
      sent: false,
    };

    this.checkTicket = this.checkTicket.bind(this);
    this.broadCastTx = this.broadCastTx.bind(this);
    this.sendBitcoin = this.sendBitcoin.bind(this);
  }

  broadCastTx(psbtHex) {
    let command = {
      'broadcast-tx': psbtHex
    }
    return this.props.api.btcWalletCommand(command)
  }

  sendBitcoin(ticket, psbt) {

    const mnemonic = kg.deriveNodeSeed(ticket, 'bitcoin');
    const seed = bip39.mnemonicToSeed(mnemonic);
    const hd = bitcoin.bip32.fromSeed(seed);

    const newPsbt = bitcoin.Psbt.fromBase64(psbt);

    const hex =
      newPsbt.data.inputs
             .reduce((psbt, input, idx) => {
               const path = input.bip32Derivation[0].path
               const prv = hd.derivePath(path).privateKey;
               return psbt.signInput(idx, bitcoin.ECPair.fromPrivateKey(prv));

             }, newPsbt)
             .finalizeAllInputs()
             .extractTransaction()
             .toHex();

    console.log({hex});
    this.broadCastTx(hex).then(res => this.setState({sent: true}));
  }

  checkTicket(e){
    // TODO: port over bridge ticket validation logic
    let masterTicket = e.target.value;
    let ready = (masterTicket.length > 0);
    this.setState({masterTicket, ready});
  }

  render() {
    const { stopSending, payee, denomination, denomAmount, satsAmount } = this.props;
    const { sent } = this.state;
    return (
      <>
        { sent ?
          <Sent
            payee={payee}
            denomination={denomination}
            denomAmount={denomAmount}
            satsAmount={satsAmount}
          /> :
          <Col
            height='400px'
            width='100%'
            backgroundColor='white'
            borderRadius='32px'
            mb={5}
            p={5}
          >
            <Row
              justifyContent='space-between'
              alignItems='center'
            >
              <Text bold fontSize={1}>Invoice</Text>
              <Icon
                icon='X'
                cursor='pointer'
                onClick={() => stopSending()}
              />
            </Row>
            <Box
              mt={4}
              backgroundColor='rgba(0, 159, 101, 0.05)'
              borderRadius='12px'
            >
              <Box
                padding={4}
              >
                <Row>
                  <Text fontSize='14px' fontWeight='500'>You are sending</Text>
                </Row>
                <Row
                  mt={2}
                >
                  <Text
                    color='green'
                    fontSize='14px'
                  >{`$${denomAmount} ${denomination}`}</Text>
                  <Text
                    ml={2}
                    fontSize='14px'
                    color='gray'
                  >{`${satsAmount} sats`}</Text>
                </Row>
                <Row
                  mt={2}
                >
                  <Text fontSize='14px'>To:</Text>
                  <Text
                    ml={2}
                    fontSize='14px'
                  >{payee}</Text>
                </Row>
              </Box>
            </Box>
            <Box mt={3} mb={2}>
              <Text gray fontSize={1} fontWeight='600'>
                Master Key
              </Text>
            </Box>
            <Input
              value={this.state.masterTicket}
              fontSize="14px"
              type="password"
              name="masterTicket"
              obscure={value => value.replace(/[^~-]+/g, '••••••')}
              placeholder="••••••-••••••-••••••-••••••"
              autoCapitalize="none"
              autoCorrect="off"
              onChange={this.checkTicket}
            />
            <Row
              flexDirection='row-reverse'
              mt={4}
            >
              <Button
                primary
                children='Send BTC'
                mr={3}
                fontSize={1}
                borderRadius='24px'
                py='24px'
                px='24px'
                onClick={() => this.sendBitcoin(this.state.masterTicket, store.state.psbt)}
                disabled={!this.state.ready}
                style={{cursor: this.state.ready ? "pointer" : "default"}}
              />
            </Row>
          </Col>
        }
      </>
    );
  }
}
<|endoftext|>


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

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import Modules from 'googlesitekit-modules';
import accounts from './accounts';
import properties from './properties';
import profiles from './profiles';
import settings from './settings';
import tags from './tags';
import { STORE_NAME } from './constants';
export { STORE_NAME };

const baseModuleStore = Modules.createModuleStore( 'analytics', {
	settingSlugs: [
		'anonymizeIP',
		'accountID',
		'profileID',
		'propertyID',
		'internalWebPropertyID',
		'useSnippet',
		'trackingDisabled',
	],
} );

export const INITIAL_STATE = Data.collectState(
	baseModuleStore.INITIAL_STATE,
	accounts.INITIAL_STATE,
	properties.INITIAL_STATE,
	profiles.INITIAL_STATE,
	settings.INITIAL_STATE,
	tags.INITIAL_STATE,
);

export const actions = Data.collectActions(
	baseModuleStore.actions,
	accounts.actions,
	properties.actions,
	profiles.actions,
	settings.actions,
	tags.actions,
);

export const controls = Data.collectControls(
	baseModuleStore.controls,
	accounts.controls,
	properties.controls,
	profiles.controls,
	settings.controls,
	tags.controls,
);

export const reducer = Data.addInitializeReducer(
	INITIAL_STATE,
	Data.collectReducers(
		baseModuleStore.reducer,
		accounts.reducer,
		properties.reducer,
		profiles.reducer,
		settings.reducer,
		tags.reducer,
	)
);

export const resolvers = Data.collectResolvers(
	baseModuleStore.resolvers,
	accounts.resolvers,
	properties.resolvers,
	profiles.resolvers,
	settings.resolvers,
	tags.resolvers,
);

export const selectors = Data.collectSelectors(
	baseModuleStore.selectors,
	accounts.selectors,
	properties.selectors,
	profiles.selectors,
	settings.selectors,
	tags.selectors,
);

const store = {
	actions,
	controls,
	reducer,
	resolvers,
	selectors,
};

// Register this store on the global registry.
Data.registerStore( STORE_NAME, store );

export default store;
<commit_msg>Pass storeName when creating Analytics store.<commit_after>/**
 * modules/analytics data store
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import Modules from 'googlesitekit-modules';
import accounts from './accounts';
import properties from './properties';
import profiles from './profiles';
import settings from './settings';
import tags from './tags';
import { STORE_NAME } from './constants';
export { STORE_NAME };

const baseModuleStore = Modules.createModuleStore( 'analytics', {
	storeName: STORE_NAME,
	settingSlugs: [
		'anonymizeIP',
		'accountID',
		'profileID',
		'propertyID',
		'internalWebPropertyID',
		'useSnippet',
		'trackingDisabled',
	],
} );

export const INITIAL_STATE = Data.collectState(
	baseModuleStore.INITIAL_STATE,
	accounts.INITIAL_STATE,
	properties.INITIAL_STATE,
	profiles.INITIAL_STATE,
	settings.INITIAL_STATE,
	tags.INITIAL_STATE,
);

export const actions = Data.collectActions(
	baseModuleStore.actions,
	accounts.actions,
	properties.actions,
	profiles.actions,
	settings.actions,
	tags.actions,
);

export const controls = Data.collectControls(
	baseModuleStore.controls,
	accounts.controls,
	properties.controls,
	profiles.controls,
	settings.controls,
	tags.controls,
);

export const reducer = Data.addInitializeReducer(
	INITIAL_STATE,
	Data.collectReducers(
		baseModuleStore.reducer,
		accounts.reducer,
		properties.reducer,
		profiles.reducer,
		settings.reducer,
		tags.reducer,
	)
);

export const resolvers = Data.collectResolvers(
	baseModuleStore.resolvers,
	accounts.resolvers,
	properties.resolvers,
	profiles.resolvers,
	settings.resolvers,
	tags.resolvers,
);

export const selectors = Data.collectSelectors(
	baseModuleStore.selectors,
	accounts.selectors,
	properties.selectors,
	profiles.selectors,
	settings.selectors,
	tags.selectors,
);

const store = {
	actions,
	controls,
	reducer,
	resolvers,
	selectors,
};

// Register this store on the global registry.
Data.registerStore( STORE_NAME, store );

export default store;
<|endoftext|>


<commit_before>/*jshint esversion: 6 */
/*
 * This file is part of Cockpit.
 *
 * Copyright (C) 2016 Red Hat, Inc.
 *
 * Cockpit is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Cockpit is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
 */

/**
 This file contains various polyfills and other compatibility hacks
 */

// for IE 11
if (!String.prototype.startsWith) {
    String.prototype.startsWith = function (searchString, position) {
        position = position || 0;
        return this.substr(position, searchString.length) === searchString;
    };
}

if (!Array.prototype.findIndex) {
    Array.prototype.findIndex = function (predicate) {
        if (this === null) {
            throw new TypeError('Array.prototype.findIndex called on null or undefined');
        }
        if (typeof predicate !== 'function') {
            throw new TypeError('predicate must be a function');
        }
        var list = Object(this);
        var length = list.length >>> 0;
        var thisArg = arguments[1];
        var value;

        for (var i = 0; i < length; i++) {
            value = list[i];
            if (predicate.call(thisArg, value, i, list)) {
                return i;
            }
        }
        return -1;
    };
}

// for IE 11
if (typeof Object.assign != 'function') {
    // Must be writable: true, enumerable: false, configurable: true
    Object.defineProperty(Object, "assign", {
        value: function assign(target, varArgs) { // .length of function is 2
            'use strict';
            if (target === null) { // TypeError if undefined or null
                throw new TypeError('Cannot convert undefined or null to object');
            }

            var to = Object(target);

            for (var index = 1; index < arguments.length; index++) {
                var nextSource = arguments[index];

                if (nextSource !== null) { // Skip over if undefined or null
                    for (var nextKey in nextSource) {
                        // Avoid bugs when hasOwnProperty is shadowed
                        if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
                            to[nextKey] = nextSource[nextKey];
                        }
                    }
                }
            }
            return to;
        },
        writable: true,
        configurable: true
    });
}
<commit_msg>polyfills.js: Add Array.prototype.find<commit_after>/*jshint esversion: 6 */
/*
 * This file is part of Cockpit.
 *
 * Copyright (C) 2016 Red Hat, Inc.
 *
 * Cockpit is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Cockpit is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
 */

/**
 This file contains various polyfills and other compatibility hacks
 */

// for IE 11
if (!String.prototype.startsWith) {
    String.prototype.startsWith = function (searchString, position) {
        position = position || 0;
        return this.substr(position, searchString.length) === searchString;
    };
}

if (!Array.prototype.findIndex) {
    Array.prototype.findIndex = function (predicate) {
        if (this === null) {
            throw new TypeError('Array.prototype.findIndex called on null or undefined');
        }
        if (typeof predicate !== 'function') {
            throw new TypeError('predicate must be a function');
        }
        var list = Object(this);
        var length = list.length >>> 0;
        var thisArg = arguments[1];
        var value;

        for (var i = 0; i < length; i++) {
            value = list[i];
            if (predicate.call(thisArg, value, i, list)) {
                return i;
            }
        }
        return -1;
    };
}

// for IE 11
if (typeof Object.assign != 'function') {
    // Must be writable: true, enumerable: false, configurable: true
    Object.defineProperty(Object, "assign", {
        value: function assign(target, varArgs) { // .length of function is 2
            'use strict';
            if (target === null) { // TypeError if undefined or null
                throw new TypeError('Cannot convert undefined or null to object');
            }

            var to = Object(target);

            for (var index = 1; index < arguments.length; index++) {
                var nextSource = arguments[index];

                if (nextSource !== null) { // Skip over if undefined or null
                    for (var nextKey in nextSource) {
                        // Avoid bugs when hasOwnProperty is shadowed
                        if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
                            to[nextKey] = nextSource[nextKey];
                        }
                    }
                }
            }
            return to;
        },
        writable: true,
        configurable: true
    });
}

// for IE 11
// https://tc39.github.io/ecma262/#sec-array.prototype.find
if (!Array.prototype.find) {
    Object.defineProperty(Array.prototype, 'find', {
        value: function(predicate) {
            // 1. Let O be ? ToObject(this value).
            if (this === null) {
                throw new TypeError('"this" is null or not defined');
            }

            var o = Object(this);

            // 2. Let len be ? ToLength(? Get(O, "length")).
            var len = o.length >>> 0;

            // 3. If IsCallable(predicate) is false, throw a TypeError exception.
            if (typeof predicate !== 'function') {
                throw new TypeError('predicate must be a function');
            }

            // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
            var thisArg = arguments[1];

            // 5. Let k be 0.
            var k = 0;

            // 6. Repeat, while k < len
            while (k < len) {
                // a. Let Pk be ! ToString(k).
                // b. Let kValue be ? Get(O, Pk).
                // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
                // d. If testResult is true, return kValue.
                var kValue = o[k];
                if (predicate.call(thisArg, kValue, k, o)) {
                    return kValue;
                }
                // e. Increase k by 1.
                k++;
            }

            // 7. Return undefined.
            return undefined;
        }
    });
}
<|endoftext|>


<commit_before>/* Copyright (c) 2013-2016 The TagSpaces Authors.
 * Use of this source code is governed by the MIT license which can be found in the LICENSE.txt file. */

/* global define, Handlebars, isCordova  */
define(function(require, exports, module) {
  "use strict";

  var extensionTitle = "Grid"; // should be equal to the name in the bower.json
  var extensionID = "perspectiveGrid"; // ID must be equal to the directory name where the extension is located
  var extensionIcon = "fa fa-th"; // icon class from font awesome

  console.log("Loading " + extensionID);

  var TSCORE = require("tscore");
  var extensionDirectory = TSCORE.Config.getExtensionPath() + "/" + extensionID;
  var UI;
  var extensionLoaded;

  function init() {
    console.log("Initializing perspective " + extensionID);

    extensionLoaded = new Promise(function(resolve, reject) {
      require([
        extensionDirectory + '/perspectiveUI.js',
        "text!" + extensionDirectory + '/toolbar.html',
        "marked",
        "css!" + extensionDirectory + '/extension.css',
      ], function(extUI, toolbarTPL, marked) {
        var toolbarTemplate = Handlebars.compile(toolbarTPL);
        UI = new extUI.ExtUI(extensionID);
        UI.buildUI(toolbarTemplate);
        platformTuning();
        if (isCordova) {
          TSCORE.reLayout();
        }
        try {
          $('#' + extensionID + 'Container [data-i18n]').i18n();
          $('#aboutExtensionModalGrid').on('show.bs.modal', function() {
            $.ajax({
              url: extensionDirectory + '/README.md',
              type: 'GET'
            })
            .done(function(mdData) {
              //console.log("DATA: " + mdData);
              if (typeof(marked) != 'undefined') {
                $("#aboutExtensionModalGrid .modal-body").html(marked(mdData));
              } else {
                $("#aboutExtensionModalGrid .modal-body").html(mdData);
                console.warn("marked function not found");
              }
            })
            .fail(function(data) {
              console.warn("Loading file failed " + data);
            });
          });

        } catch (err) {
          console.log("Failed translating extension");
        }
        resolve(true);
      });
    });
  }

  function platformTuning() {
    if (isCordova) {
      $("#" + extensionID + "IncludeSubDirsButton").hide();
      $('#' + extensionID + 'AddFileButton').hide(); // TODO tmp disabled due not working binary saving
    } else if (isChrome) {
      $('#' + extensionID + 'AddFileButton').hide();
      $('#' + extensionID + 'TagButton').hide();
      $('#' + extensionID + 'CopyMoveButton').hide();
      $('#' + extensionID + 'CreateDirectoryButton').hide();
    } else if (isFirefox) {
      $('#' + extensionID + 'AddFileButton').hide(); // Current impl has 0.5mb limit
    }
  }

  function load() {
    console.log("Loading perspective " + extensionID);
    extensionLoaded.then(function() {
      UI.reInit();
    }, function(err) {
      console.warn("Loading extension failed: " + err);
    });
  }

  function clearSelectedFiles() {
    if (UI) {
      UI.clearSelectedFiles();
      UI.handleElementActivation();
    }
  }

  function removeFileUI(filePath) {

    UI.removeFileUI(filePath);
  }

  function updateFileUI(oldFilePath, newFilePath) {

    UI.updateFileUI(oldFilePath, newFilePath);
  }

  function getNextFile(filePath) {

    return UI.getNextFile(filePath);
  }

  function getPrevFile(filePath) {

    return UI.getPrevFile(filePath);
  }

  function updateTreeData(fsTreeData) {

    console.log("Updating tree data not implemented");
  }

  // API Vars
  exports.Title = extensionTitle;
  exports.ID = extensionID;
  exports.Icon = extensionIcon;

  // API Methods
  exports.init = init;
  exports.load = load;
  exports.clearSelectedFiles = clearSelectedFiles;
  exports.getNextFile = getNextFile;
  exports.getPrevFile = getPrevFile;
  exports.removeFileUI = removeFileUI;
  exports.updateFileUI = updateFileUI;
  exports.updateTreeData = updateTreeData;

});
<commit_msg>fix about open about only if found marked function -- issue TS287<commit_after>/* Copyright (c) 2013-2016 The TagSpaces Authors.
 * Use of this source code is governed by the MIT license which can be found in the LICENSE.txt file. */

/* global define, Handlebars, isCordova  */
define(function(require, exports, module) {
  "use strict";

  var extensionTitle = "Grid"; // should be equal to the name in the bower.json
  var extensionID = "perspectiveGrid"; // ID must be equal to the directory name where the extension is located
  var extensionIcon = "fa fa-th"; // icon class from font awesome

  console.log("Loading " + extensionID);

  var TSCORE = require("tscore");
  var extensionDirectory = TSCORE.Config.getExtensionPath() + "/" + extensionID;
  var UI;
  var extensionLoaded;

  function init() {
    console.log("Initializing perspective " + extensionID);

    extensionLoaded = new Promise(function(resolve, reject) {
      require([
        extensionDirectory + '/perspectiveUI.js',
        "text!" + extensionDirectory + '/toolbar.html',
        "marked",
        "css!" + extensionDirectory + '/extension.css',
      ], function(extUI, toolbarTPL, marked) {
        var toolbarTemplate = Handlebars.compile(toolbarTPL);
        UI = new extUI.ExtUI(extensionID);
        UI.buildUI(toolbarTemplate);
        platformTuning();
        if (isCordova) {
          TSCORE.reLayout();
        }
        try {
          $('#' + extensionID + 'Container [data-i18n]').i18n();
          $('#aboutExtensionModalGrid').on('show.bs.modal', function() {
            $.ajax({
              url: extensionDirectory + '/README.md',
              type: 'GET'
            })
            .done(function(mdData) {
              //console.log("DATA: " + mdData);
              if (marked) {
                $("#aboutExtensionModalGrid .modal-body").html(marked(mdData));
              } else {
                console.warn("marked function not found");
              }
            })
            .fail(function(data) {
              console.warn("Loading file failed " + data);
            });
          });

        } catch (err) {
          console.log("Failed translating extension");
        }
        resolve(true);
      });
    });
  }

  function platformTuning() {
    if (isCordova) {
      $("#" + extensionID + "IncludeSubDirsButton").hide();
      $('#' + extensionID + 'AddFileButton').hide(); // TODO tmp disabled due not working binary saving
    } else if (isChrome) {
      $('#' + extensionID + 'AddFileButton').hide();
      $('#' + extensionID + 'TagButton').hide();
      $('#' + extensionID + 'CopyMoveButton').hide();
      $('#' + extensionID + 'CreateDirectoryButton').hide();
    } else if (isFirefox) {
      $('#' + extensionID + 'AddFileButton').hide(); // Current impl has 0.5mb limit
    }
  }

  function load() {
    console.log("Loading perspective " + extensionID);
    extensionLoaded.then(function() {
      UI.reInit();
    }, function(err) {
      console.warn("Loading extension failed: " + err);
    });
  }

  function clearSelectedFiles() {
    if (UI) {
      UI.clearSelectedFiles();
      UI.handleElementActivation();
    }
  }

  function removeFileUI(filePath) {

    UI.removeFileUI(filePath);
  }

  function updateFileUI(oldFilePath, newFilePath) {

    UI.updateFileUI(oldFilePath, newFilePath);
  }

  function getNextFile(filePath) {

    return UI.getNextFile(filePath);
  }

  function getPrevFile(filePath) {

    return UI.getPrevFile(filePath);
  }

  function updateTreeData(fsTreeData) {

    console.log("Updating tree data not implemented");
  }

  // API Vars
  exports.Title = extensionTitle;
  exports.ID = extensionID;
  exports.Icon = extensionIcon;

  // API Methods
  exports.init = init;
  exports.load = load;
  exports.clearSelectedFiles = clearSelectedFiles;
  exports.getNextFile = getNextFile;
  exports.getPrevFile = getPrevFile;
  exports.removeFileUI = removeFileUI;
  exports.updateFileUI = updateFileUI;
  exports.updateTreeData = updateTreeData;

});
<|endoftext|>


<commit_before>$(document).ready(function(){
	var currencies = [];
	var clickedElement = {};

	//Fetches newest exchange rate
	function getLatestExt(){
		chrome.runtime.sendMessage({req: "currency"}, function(response) {
			currencies = JSON.parse(response.currency);
		  /*
			$('body *').each(function(){
				var obj = $(this).text();
				var match = obj.match(/^\$\d+(?:\.\d+)?\s*$/);
				if(match){
					var number = Number(obj.replace(/[^0-9\.]+/g,""));
					$(this).append('

'+Math.round(currencies[0].value*number)+' Kr

  ');
				}
			});
		*/
	})
	};
	//Do this once
	getLatestExt();

	$(document).on('mousedown', function(event){
		clickedElement = $(event.target);
	})

	chrome.runtime.onMessage.addListener(
		function(request, sender, sendResponse) {
			if (request.req == "convert"){
				console.log(clickedElement.text());
			}
		});

	function deselect(element) {
		element.slideFadeToggle(function() {
			element.next().removeClass("selected");
		});
	}

	$(function() {
		$(document).on('click','#peningar', function() {
			var tooltip = $(this).prev();
			if(tooltip.hasClass("selected")) {
				deselect(tooltip);
			} else {
				tooltip.addClass("selected");
				tooltip.css('top',$(this).position().top+20);
				tooltip.css('left',$(this).position().left);
				tooltip.slideFadeToggle();
			}
			return false;
		});

	});

	$.fn.slideFadeToggle = function(easing, callback) {
		return this.animate({ opacity: 'toggle', height: 'toggle' }, "fast", easing, callback);
	};

});<commit_msg>Flag or no flag?<commit_after>$(document).ready(function(){
	var currencies = [];
	var clickedElement = {};

	//Fetches newest exchange rate
	function getLatestExt(){
		chrome.runtime.sendMessage({req: "currency"}, function(response) {
			currencies = JSON.parse(response.currency);
		  /*
			$('body *').each(function(){
				var obj = $(this).text();
				var match = obj.match(/^\$\d+(?:\.\d+)?\s*$/);
				if(match){
					var number = Number(obj.replace(/[^0-9\.]+/g,""));
					$(this).append('

'+Math.round(currencies[0].value*number)+' Kr

  ');
				}
			});
		*/
	})
	};
	//Do this once
	getLatestExt();

	$(document).on('mousedown', function(event){
		clickedElement = $(event.target);
	})

	chrome.runtime.onMessage.addListener(
		function(request, sender, sendResponse) {
			if (request.req == "convert"){
				var obj = clickedElement.text();
				var match = obj.match(/^\$\d+(?:\.\d+)?\s*$/);
				if(match){
					var number = Number(obj.replace(/[^0-9\.]+/g,""));
					var currElement = $('#local');
					//currElement.val(number);
					//console.log(number);
					clickedElement.append('

'+Math.round(currencies[0].value*number)+' Kr

  ');
				}
			}
		});

	function deselect(element) {
		element.slideFadeToggle(function() {
			element.next().removeClass("selected");
		});
	}

	$(function() {
		$(document).on('click','#peningar', function() {
			var tooltip = $(this).prev();
			if(tooltip.hasClass("selected")) {
				deselect(tooltip);
			} else {
				tooltip.addClass("selected");
				tooltip.css('top',$(this).position().top+20);
				tooltip.css('left',$(this).position().left);
				tooltip.slideFadeToggle();
			}
			return false;
		});

	});

	$.fn.slideFadeToggle = function(easing, callback) {
		return this.animate({ opacity: 'toggle', height: 'toggle' }, "fast", easing, callback);
	};

});<|endoftext|>


<commit_before>'use strict';

const St = imports.gi.St;
const Main = imports.ui.main;
const GnomeDesktop = imports.gi.GnomeDesktop;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Util = imports.misc.util;
const Config = imports.misc.config;

const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;

const log_this = Convenience.log_this;
const version_data = Convenience.version_data;
const isGnome40 = Convenience.isGnome40;

let text, button, label;
let clock, clock_signal_id;
let settings;

let signals = [];

let shellMinorVersion36 = parseInt(version_data[1]) < 36;

let format_params = {
    hour: '2-digit',
    minute: '2-digit',
    hour12: false
}
let time_text = 'UTC';

function init() {
    settings = Convenience.getSettings();

    clock = new GnomeDesktop.WallClock();
    button = new St.Bin({
        style_class: 'panel-button',
        reactive: true,
        can_focus: false,
        x_expand: true,
        y_expand: false,
        y_align: !isGnome40 && shellMinorVersion36 ? St.Align.MIDDLE : St.Align.END,
        track_hover: true
    });

    label = new St.Label({
        opacity: 200
    });

    button.set_child(label);
    log_this(Config.PACKAGE_VERSION);
}

function enable() {
    log_this(`enabling...`);

    signals[0] = settings.connect('changed::show-seconds', Lang.bind(this, setSecondsDisplayed));
    signals[1] = settings.connect('changed::time-text', Lang.bind(this, setTimeText));
    signals[2] = settings.connect('changed::show-date', Lang.bind(this, setDateDisplayed));
    signals[3] = settings.connect('changed::light-opacity', Lang.bind(this, setLightOpacity));

    signals[4] = button.connect('button-press-event', showMenu);
    setSecondsDisplayed();
    setTimeText();
    setDateDisplayed();
    setLightOpacity();

    update_time();
    signals[5] = clock.connect('notify::clock', Lang.bind(this, this.update_time));
    Main.panel._centerBox.insert_child_at_index(button, 1);
    log_this(`enabled.`);
}

function disable() {
    log_this(`disabling...`);

    settings.disconnect(signals[0]);
    settings.disconnect(signals[1]);
    settings.disconnect(signals[2]);
    settings.disconnect(signals[3]);
    button.disconnect(signals[4]);

    Main.panel._centerBox.remove_child(button);
    clock.disconnect(signals[5]);
    log_this(`disabled.`);
}

function update_time() {
    var now = new Date();
    var utc = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds());
    label.set_text(new Intl.DateTimeFormat('default', format_params).format(utc) + ' ' + time_text);
}

function setSecondsDisplayed() {
    let secondsDisplayed = settings.get_boolean('show-seconds');
    if (secondsDisplayed) {
        format_params['second'] = '2-digit';
    } else {
        delete format_params['second'];
    }
    update_time();
}

function setTimeText() {
    time_text = settings.get_string('time-text');
    update_time();
}

function setDateDisplayed() {
    let dateDisplayed = settings.get_boolean('show-date');
    if (dateDisplayed) {
        format_params['weekday'] = 'short';
        format_params['month'] = 'short';
        format_params['day'] = 'numeric';
    } else {
        delete format_params['weekday'];
        delete format_params['month'];
        delete format_params['day'];
    }
    update_time();
}

function setLightOpacity() {
    label.opacity = settings.get_boolean('light-opacity') ? 255 : 200;
    update_time();
}

function showMenu() {
    Util.spawn([
        "gnome-shell-extension-prefs",
        Me.uuid
    ]);
}
<commit_msg>Code ordering<commit_after>'use strict';

const St = imports.gi.St;
const Main = imports.ui.main;
const GnomeDesktop = imports.gi.GnomeDesktop;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Util = imports.misc.util;
const Config = imports.misc.config;

const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;

const log_this = Convenience.log_this;
const version_data = Convenience.version_data;
const isGnome40 = Convenience.isGnome40;

let text, button, label;
let clock, clock_signal_id;
let settings;

let signals = [];

let shellMinorVersion36 = parseInt(version_data[1]) < 36;

let format_params = {
    hour: '2-digit',
    minute: '2-digit',
    hour12: false
}
let time_text = 'UTC';

function init() {
    settings = Convenience.getSettings();

    clock = new GnomeDesktop.WallClock();
    button = new St.Bin({
        style_class: 'panel-button',
        reactive: true,
        can_focus: false,
        x_expand: true,
        y_expand: false,
        y_align: !isGnome40 && shellMinorVersion36 ? St.Align.MIDDLE : St.Align.END,
        track_hover: true
    });

    label = new St.Label({
        opacity: 200
    });

    button.set_child(label);
    log_this(Config.PACKAGE_VERSION);
}

function enable() {
    log_this(`enabling...`);

    signals[0] = settings.connect('changed::show-seconds', Lang.bind(this, setSecondsDisplayed));
    signals[1] = settings.connect('changed::time-text', Lang.bind(this, setTimeText));
    signals[2] = settings.connect('changed::show-date', Lang.bind(this, setDateDisplayed));
    signals[3] = settings.connect('changed::light-opacity', Lang.bind(this, setLightOpacity));

    signals[4] = button.connect('button-press-event', showMenu);

    setSecondsDisplayed();
    setTimeText();
    setDateDisplayed();
    setLightOpacity();

    update_time();
    signals[5] = clock.connect('notify::clock', Lang.bind(this, this.update_time));
    Main.panel._centerBox.insert_child_at_index(button, 1);
    log_this(`enabled.`);
}

function disable() {
    log_this(`disabling...`);

    settings.disconnect(signals[0]);
    settings.disconnect(signals[1]);
    settings.disconnect(signals[2]);
    settings.disconnect(signals[3]);
    button.disconnect(signals[4]);

    Main.panel._centerBox.remove_child(button);
    clock.disconnect(signals[5]);
    log_this(`disabled.`);
}

function update_time() {
    var now = new Date();
    var utc = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds());
    label.set_text(new Intl.DateTimeFormat('default', format_params).format(utc) + ' ' + time_text);
}

function setSecondsDisplayed() {
    let secondsDisplayed = settings.get_boolean('show-seconds');
    if (secondsDisplayed) {
        format_params['second'] = '2-digit';
    } else {
        delete format_params['second'];
    }
    update_time();
}

function setTimeText() {
    time_text = settings.get_string('time-text');
    update_time();
}

function setDateDisplayed() {
    let dateDisplayed = settings.get_boolean('show-date');
    if (dateDisplayed) {
        format_params['weekday'] = 'short';
        format_params['month'] = 'short';
        format_params['day'] = 'numeric';
    } else {
        delete format_params['weekday'];
        delete format_params['month'];
        delete format_params['day'];
    }
    update_time();
}

function setLightOpacity() {
    label.opacity = settings.get_boolean('light-opacity') ? 255 : 200;
    update_time();
}

function showMenu() {
    Util.spawn([
        "gnome-shell-extension-prefs",
        Me.uuid
    ]);
}
<|endoftext|>


<commit_before>var assert = require("assert");
var path = require("path");

var mammoth = require("../");

var testing = require("./testing");
var test = testing.test;
var testData = testing.testData;
var createFakeDocxFile = testing.createFakeDocxFile;

describe('mammoth', function() {
    test('should convert docx containing one paragraph to single p element', function() {
        var docxPath = path.join(__dirname, "test-data/single-paragraph.docx");
        return mammoth.convertToHtml({path: docxPath}).then(function(result) {
            assert.equal(result.value, "
Walking on imported air
");
            assert.deepEqual(result.messages, []);
        });
    });

    test('style map can be expressed as string', function() {
        var docxFile = createFakeDocxFile({
            "word/document.xml": testData("simple/word/document.xml")
        });
        var options = {
            styleMap: "p => h1"
        };
        return mammoth.convertToHtml({file: docxFile}, options).then(function(result) {
            assert.equal("
Hello.
", result.value);
        });
    });

    test('style map can be expressed as array of style mappings', function() {
        var docxFile = createFakeDocxFile({
            "word/document.xml": testData("simple/word/document.xml")
        });
        var options = {
            styleMap: ["p => h1"]
        };
        return mammoth.convertToHtml({file: docxFile}, options).then(function(result) {
            assert.equal("
Hello.
", result.value);
        });
    });

    test('options are passed to document converter when calling mammoth.convertToHtml', function() {
        var docxFile = createFakeDocxFile({
            "word/document.xml": testData("simple/word/document.xml")
        });
        var options = {
            styleMap: "p => h1"
        };
        return mammoth.convertToHtml({file: docxFile}, options).then(function(result) {
            assert.equal("
Hello.
", result.value);
        });
    });

    test('options.transformDocument is used to transform document if set', function() {
        var docxFile = createFakeDocxFile({
            "word/document.xml": testData("simple/word/document.xml")
        });
        var options = {
            transformDocument: function(document) {
                document.children[0].styleId = "Heading1";
                return document;
            }
        };
        return mammoth.convertToHtml({file: docxFile}, options).then(function(result) {
            assert.equal("
Hello.
", result.value);
        });
    });

    test('inline images are included in output', function() {
        var docxPath = path.join(__dirname, "test-data/tiny-picture.docx");
        return mammoth.convertToHtml({path: docxPath}).then(function(result) {
            assert.equal(result.value, '

');
        });
    });

    test('src of inline images can be changed', function() {
        var docxPath = path.join(__dirname, "test-data/tiny-picture.docx");
        var convertImage = mammoth.images.inline(function(element) {
            return element.read("base64").then(function(encodedImage) {
                return {src: encodedImage.substring(0, 2) + "," + element.contentType};
            });
        });
        return mammoth.convertToHtml({path: docxPath}, {convertImage: convertImage}).then(function(result) {
            assert.equal(result.value, '

');
        });
    });

    test('simple list is converted to list elements', function() {
        var docxPath = path.join(__dirname, "test-data/simple-list.docx");
        return mammoth.convertToHtml({path: docxPath}).then(function(result) {
            assert.equal(result.value, '

Apple

Banana

');
        });
    });

    test('word tables are converted to html tables', function() {
        var docxPath = path.join(__dirname, "test-data/tables.docx");
        return mammoth.convertToHtml({path: docxPath}).then(function(result) {
            var expectedHtml = "
Above
" +
                "
" +
                "

Top left

Top right

" +
                "

Bottom left

Bottom right

" +
                "
" +
                "
Below
";
            assert.equal(result.value, expectedHtml);
            assert.deepEqual(result.messages, []);
        });
    });

    test('footnotes are appended to text', function() {
        // TODO: don't duplicate footnotes with multiple references
        var docxPath = path.join(__dirname, "test-data/footnotes.docx");
        var options = {
            generateUniquifier: function() { return 42; }
        };
        return mammoth.convertToHtml({path: docxPath}, options).then(function(result) {
            var expectedOutput = '
Ouch' +
                '[1].' +
                '[2]
' +
                '

 A tachyon walks into a bar. ↑

' +
                '

 Fin. ↑

';
            assert.equal(result.value, expectedOutput);
            // TODO: get rid of warnings
            //~ assert.deepEqual(result.messages, []);
        });
    });

    test('indentation is used if prettyPrint is true', function() {
        var docxPath = path.join(__dirname, "test-data/single-paragraph.docx");
        return mammoth.convertToHtml({path: docxPath}, {prettyPrint: true}).then(function(result) {
            assert.equal(result.value, "
\n  Walking on imported air\n
");
            assert.deepEqual(result.messages, []);
        });
    });

    test('using styleMapping throws error', function() {
        try {
            mammoth.styleMapping();
        } catch (error) {
            assert.equal(
                error.message,
                'Use a raw string instead of mammoth.styleMapping e.g. "p[style-naming=\'Title\'] => h1" instead of mammoth.styleMapping("p[style-naming=\'Title\'] => h1")'
            );
        }
    });

    test('extractRawText only retains raw text', function() {
        var docxPath = path.join(__dirname, "test-data/simple-list.docx");
        return mammoth.extractRawText({path: docxPath}).then(function(result) {
            assert.equal(result.value, 'Apple\n\nBanana\n\n');
        });
    });
});
<commit_msg>Fix typo in tests<commit_after>var assert = require("assert");
var path = require("path");

var mammoth = require("../");

var testing = require("./testing");
var test = testing.test;
var testData = testing.testData;
var createFakeDocxFile = testing.createFakeDocxFile;

describe('mammoth', function() {
    test('should convert docx containing one paragraph to single p element', function() {
        var docxPath = path.join(__dirname, "test-data/single-paragraph.docx");
        return mammoth.convertToHtml({path: docxPath}).then(function(result) {
            assert.equal(result.value, "
Walking on imported air
");
            assert.deepEqual(result.messages, []);
        });
    });

    test('style map can be expressed as string', function() {
        var docxFile = createFakeDocxFile({
            "word/document.xml": testData("simple/word/document.xml")
        });
        var options = {
            styleMap: "p => h1"
        };
        return mammoth.convertToHtml({file: docxFile}, options).then(function(result) {
            assert.equal("
Hello.
", result.value);
        });
    });

    test('style map can be expressed as array of style mappings', function() {
        var docxFile = createFakeDocxFile({
            "word/document.xml": testData("simple/word/document.xml")
        });
        var options = {
            styleMap: ["p => h1"]
        };
        return mammoth.convertToHtml({file: docxFile}, options).then(function(result) {
            assert.equal("
Hello.
", result.value);
        });
    });

    test('options are passed to document converter when calling mammoth.convertToHtml', function() {
        var docxFile = createFakeDocxFile({
            "word/document.xml": testData("simple/word/document.xml")
        });
        var options = {
            styleMap: "p => h1"
        };
        return mammoth.convertToHtml({file: docxFile}, options).then(function(result) {
            assert.equal("
Hello.
", result.value);
        });
    });

    test('options.transformDocument is used to transform document if set', function() {
        var docxFile = createFakeDocxFile({
            "word/document.xml": testData("simple/word/document.xml")
        });
        var options = {
            transformDocument: function(document) {
                document.children[0].styleId = "Heading1";
                return document;
            }
        };
        return mammoth.convertToHtml({file: docxFile}, options).then(function(result) {
            assert.equal("
Hello.
", result.value);
        });
    });

    test('inline images are included in output', function() {
        var docxPath = path.join(__dirname, "test-data/tiny-picture.docx");
        return mammoth.convertToHtml({path: docxPath}).then(function(result) {
            assert.equal(result.value, '

');
        });
    });

    test('src of inline images can be changed', function() {
        var docxPath = path.join(__dirname, "test-data/tiny-picture.docx");
        var convertImage = mammoth.images.inline(function(element) {
            return element.read("base64").then(function(encodedImage) {
                return {src: encodedImage.substring(0, 2) + "," + element.contentType};
            });
        });
        return mammoth.convertToHtml({path: docxPath}, {convertImage: convertImage}).then(function(result) {
            assert.equal(result.value, '

');
        });
    });

    test('simple list is converted to list elements', function() {
        var docxPath = path.join(__dirname, "test-data/simple-list.docx");
        return mammoth.convertToHtml({path: docxPath}).then(function(result) {
            assert.equal(result.value, '

Apple

Banana

');
        });
    });

    test('word tables are converted to html tables', function() {
        var docxPath = path.join(__dirname, "test-data/tables.docx");
        return mammoth.convertToHtml({path: docxPath}).then(function(result) {
            var expectedHtml = "
Above
" +
                "
" +
                "

Top left

Top right

" +
                "

Bottom left

Bottom right

" +
                "
" +
                "
Below
";
            assert.equal(result.value, expectedHtml);
            assert.deepEqual(result.messages, []);
        });
    });

    test('footnotes are appended to text', function() {
        // TODO: don't duplicate footnotes with multiple references
        var docxPath = path.join(__dirname, "test-data/footnotes.docx");
        var options = {
            generateUniquifier: function() { return 42; }
        };
        return mammoth.convertToHtml({path: docxPath}, options).then(function(result) {
            var expectedOutput = '
Ouch' +
                '[1].' +
                '[2]
' +
                '

 A tachyon walks into a bar. ↑

' +
                '

 Fin. ↑

';
            assert.equal(result.value, expectedOutput);
            // TODO: get rid of warnings
            //~ assert.deepEqual(result.messages, []);
        });
    });

    test('indentation is used if prettyPrint is true', function() {
        var docxPath = path.join(__dirname, "test-data/single-paragraph.docx");
        return mammoth.convertToHtml({path: docxPath}, {prettyPrint: true}).then(function(result) {
            assert.equal(result.value, "
\n  Walking on imported air\n
");
            assert.deepEqual(result.messages, []);
        });
    });

    test('using styleMapping throws error', function() {
        try {
            mammoth.styleMapping();
        } catch (error) {
            assert.equal(
                error.message,
                'Use a raw string instead of mammoth.styleMapping e.g. "p[style-name=\'Title\'] => h1" instead of mammoth.styleMapping("p[style-name=\'Title\'] => h1")'
            );
        }
    });

    test('extractRawText only retains raw text', function() {
        var docxPath = path.join(__dirname, "test-data/simple-list.docx");
        return mammoth.extractRawText({path: docxPath}).then(function(result) {
            assert.equal(result.value, 'Apple\n\nBanana\n\n');
        });
    });
});
<|endoftext|>


<commit_before>'use strict';

var nconf = require.main.require('nconf');
var winston = require.main.require('winston');
var async = require.main.require('async');
var db = require.main.require('./src/database');
// used for standard upload functionality
var meta = require.main.require('./src/meta');
var validator = require.main.require('validator');
var file = require.main.require('./src/file');
//
var fs = require('fs');
var path = require('path');
var xxh = require('xxhash');

var ExpiringUploads = {
  // relative to nconf.get('base_dir')
  storage: '/expiring_uploads/',
  hiddenTypes: ['.zip', '.rar', '.txt', '.html'],
  expireAfter: 1000 * 60 * 60 * 24 // 24 hours
};
ExpiringUploads.Admin = {};

ExpiringUploads.init = function(app, cb) {
  async.waterfall([
    function(next) {
      // get config or create if none found
      db.getObject('settings:expiring-uploads', function(err, config) {
        if (err || !config) {
          config = {
            storage: ExpiringUploads.storage,
            expireAfter: ExpiringUploads.expireAfter,
            hiddenTypes: ExpiringUploads.hiddenTypes,
            lastID: '0'
          };
          db.setObject('settings:expiring-uploads', config);
        } else {
          ExpiringUploads.storage = config.storage;
          ExpiringUploads.expireAfter = parseInt(config.expireAfter, 10);
          ExpiringUploads.hiddenTypes = config.hiddenTypes.split(',');
        }
        next();
      });
    },
    function(next) {
      // everything in /public is out of the question, since it is
      // automatically exposed to the public (hence the name - maybe? ^_^)
      var pubTestPath = nconf.get('base_dir') + '/public';
      if (ExpiringUploads.storage.indexOf(pubTestPath) > -1) {
        winston.error('[plugin:expiring-uploads] Upload directory is ' +
                      'publicly accessible. Refusing to activate plugin!');
        return next(new Error('Public directory \'' + pubTestPath +
                              '\' not allowed as storage.'));
      }
      next();
    },
    function(next) {
      var absPath = nconf.get('base_dir') + ExpiringUploads.storage;
      // create 'storage' directory
      fs.mkdir(absPath, function(err) {
        if (err) {
          if (err.code === 'EEXIST') {
            // if folder exists, we're good.
            // could become a point to do some cleanup, though.
            return next();
          } else {
            // unexpected error; scream panic back into the log ;)
            winston.error('[plugin:expiring-uploads] Unexpected error while ' +
                          'creating ' + absPath);
            return next(err);
          }
        }
        winston.warn('[plugin:expiring-uploads] Storage folder \'' +
                        absPath + '\' not found. Created it.');
        next();
      });
    }],
    function(err) {
      if (err) {
        return cb(err);
      }
      // setup route to catch file requests
      app.router.get(nconf.get('upload_url') + ':hash/:tstamp/:fname',
                     ExpiringUploads.resolveRequest);
      cb(null, app);
    });
};

ExpiringUploads.handleUpload = function(data, cb) {
  if (ExpiringUploads.hiddenTypes.indexOf(path.extname(data.file.name)) > -1) {
    var tstamp = Date.now();
    // only used for the link; all internals use the numeric tstamp
    var hexTstamp = tstamp.toString(16);
    var filename = tstamp + '-' +
                   validator.escape(data.file.name).substr(0, 255);
    var imgData = {
      tstamp: tstamp,
      hexTstamp: hexTstamp,
      expiration: tstamp + ExpiringUploads.expireAfter,
      safePath: ExpiringUploads.storage + filename,
      hash: ExpiringUploads.getHash(data)
    };

    async.parallel({
      fs: function(next) {
        ExpiringUploads.saveFile(data.file.path, imgData.safePath, next);
      },
      db: function(next) {
        ExpiringUploads.writeToDB(imgData, next);
      }
    }, function(err) {
      if (err) {
        return cb(err);
      }
      cb(null, {
        url: nconf.get('upload_url') + imgData.hash + '/' + hexTstamp +
             '/' + data.file.name,
        name: data.file.name
      });
    });
  } else {
    ExpiringUploads.doStandard(data, cb);
  }
};

ExpiringUploads.getHash = function(imgData) {
  // key is generated from 'NodeBB secret'
  var key = nconf.get('secret');
  key = parseInt('0x' + key.substring(0, key.indexOf('-')), 16);
  return xxh.hash(new Buffer(JSON.stringify(imgData)), key).toString(16);
};

ExpiringUploads.doStandard = function(data, cb) {
  if (parseInt(meta.config.allowFileUploads, 10) !== 1) {
    return cb(new Error('[[error:uploads-are-disabled]]'));
  }

  if (!data.file) {
    return cb(new Error('[[error:invalid-file]]'));
  }

  if (data.file.size > parseInt(meta.config.maximumFileSize, 10) * 1024) {
    return cb(new Error('[[error:file-too-big, ' +
                        meta.config.maximumFileSize + ']]'));
  }

  var filename = data.file.name || 'upload';

  filename = Date.now() + '-' + validator.escape(filename).substr(0, 255);
  file.saveFileToLocal(filename, 'files', data.file.path,
                       function(err, upload) {
    if (err) {
      return cb(err);
    }
    cb(null, {
			url: nconf.get('relative_path') + upload.url,
      name: data.file.name
		});
  });
};

ExpiringUploads.saveFile = function(src, dest, cb) {
  var is = fs.createReadStream(src);
  var os = fs.createWriteStream(nconf.get('base_dir') + dest);

  is.on('end', cb);
  os.on('error', cb);
  is.pipe(os);
};

ExpiringUploads.writeToDB = function(imgData, cb) {
  async.waterfall([
    function(next) {
      db.incrObjectField('settings:expiring-uploads', 'lastID', next);
    },
    function(id, next) {
      db.sortedSetAdd('expiring-uploads:ids', imgData.tstamp, id, function() {
        return next(null, id);
      });
    },
    function(id, next) {
      db.setObject('expiring-uploads:' + id, imgData, next);
    }
  ],
  function(err) {
    if (err) {
      return cb(err);
    }
  });
  return cb();
};

ExpiringUploads.resolveRequest = function(req, res, cb) {
  var hash = req.params.hash;
  // timestamp comes in as hex string
  var tstamp = parseInt('0x' + req.params.tstamp, 16);
  var fname = req.params.fname;

  // return when file (according to request url) is expired.
  // the url could be wrong, but then it's up for grabs, anyway :)
  if (Date.now() > tstamp + ExpiringUploads.expireAfter) {
    return ExpiringUploads.sendGone();
  }
  async.waterfall([
    function(next) {
      // get ID of upload
      db.getSortedSetRevRangeByScore('expiring-uploads:ids', 0, 1,
                                     tstamp, tstamp, next);
    },
    function(id, next) {
      if (id.length === 0) {
        return ExpiringUploads.sendGone(req, res);
      }
      // get upload info to perform checks
      db.getObjectFields('expiring-uploads:' + id[0],
                         ['hash', 'tstamp', 'safePath'], next);
    }], function(err, fields) {
      if (err) {
        return cb(err);
      }
      var hashMatch = (fields.hash === hash);
      var timeMatch = (parseInt(fields.tstamp, 10) === tstamp);
      var nameMatch = (path.basename(fields.safePath) === tstamp + '-' + fname);
      if (hashMatch && timeMatch && nameMatch) {
        res.status(200);
        // tell (not force! It's not part of the HTTP standard.) the browser
        // to download the file, even if it has a recognized/handled MIME.
        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1
        res.setHeader('Content-Disposition', 'attachement');
        res.sendFile(nconf.get('base_dir') + fields.safePath);
      }
    });
};

ExpiringUploads.sendGone = function(req, res) {
  var mw = require.main.require('./src/middleware/middleware')(req.app);
  // 410 Gone
  // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.11
  res.status(410);
  mw.buildHeader(req, res, function() {
    // add custom template
    res.render('404', {path: res.path});
  });
};

ExpiringUploads.Admin.addMenuItem = function(custom_header, cb) {
  custom_header.plugins.push({
    route: '/plugins/expups',
    icon: 'fa-clock-o',
    name: 'ExpiringUploads'
  });
  cb(null, custom_header);
};

module.exports = ExpiringUploads;
<commit_msg>Store filename only.<commit_after>'use strict';

var nconf = require.main.require('nconf');
var winston = require.main.require('winston');
var async = require.main.require('async');
var db = require.main.require('./src/database');
// used for standard upload functionality
var meta = require.main.require('./src/meta');
var validator = require.main.require('validator');
var file = require.main.require('./src/file');
//
var fs = require('fs');
var path = require('path');
var xxh = require('xxhash');

var ExpiringUploads = {
  // relative to nconf.get('base_dir')
  storage: '/expiring_uploads/',
  hiddenTypes: ['.zip', '.rar', '.txt', '.html'],
  expireAfter: 1000 * 60 * 60 * 24 // 24 hours
};
ExpiringUploads.Admin = {};

ExpiringUploads.init = function(app, cb) {
  async.waterfall([
    function(next) {
      // get config or create if none found
      db.getObject('settings:expiring-uploads', function(err, config) {
        if (err || !config) {
          config = {
            storage: ExpiringUploads.storage,
            expireAfter: ExpiringUploads.expireAfter,
            hiddenTypes: ExpiringUploads.hiddenTypes,
            lastID: '0'
          };
          db.setObject('settings:expiring-uploads', config);
        } else {
          ExpiringUploads.storage = config.storage;
          ExpiringUploads.expireAfter = parseInt(config.expireAfter, 10);
          ExpiringUploads.hiddenTypes = config.hiddenTypes.split(',');
        }
        next();
      });
    },
    function(next) {
      // everything in /public is out of the question, since it is
      // automatically exposed to the public (hence the name - maybe? ^_^)
      var pubTestPath = nconf.get('base_dir') + '/public';
      if (ExpiringUploads.storage.indexOf(pubTestPath) > -1) {
        winston.error('[plugin:expiring-uploads] Upload directory is ' +
                      'publicly accessible. Refusing to activate plugin!');
        return next(new Error('Public directory \'' + pubTestPath +
                              '\' not allowed as storage.'));
      }
      next();
    },
    function(next) {
      var absPath = nconf.get('base_dir') + ExpiringUploads.storage;
      // create 'storage' directory
      fs.mkdir(absPath, function(err) {
        if (err) {
          if (err.code === 'EEXIST') {
            // if folder exists, we're good.
            // could become a point to do some cleanup, though.
            return next();
          } else {
            // unexpected error; scream panic back into the log ;)
            winston.error('[plugin:expiring-uploads] Unexpected error while ' +
                          'creating ' + absPath);
            return next(err);
          }
        }
        winston.warn('[plugin:expiring-uploads] Storage folder \'' +
                        absPath + '\' not found. Created it.');
        next();
      });
    }],
    function(err) {
      if (err) {
        return cb(err);
      }
      // setup route to catch file requests
      app.router.get(nconf.get('upload_url') + ':hash/:tstamp/:fname',
                     ExpiringUploads.resolveRequest);
      cb(null, app);
    });
};

ExpiringUploads.handleUpload = function(data, cb) {
  if (ExpiringUploads.hiddenTypes.indexOf(path.extname(data.file.name)) > -1) {
    var tstamp = Date.now();
    // only used for the link; all internals use the numeric tstamp
    var hexTstamp = tstamp.toString(16);
    var filename = tstamp + '-' + validator.escape(data.file.name)
                                  .substr(0, 255).toLowerCase();
    var imgData = {
      tstamp: tstamp,
      hexTstamp: hexTstamp,
      expiration: tstamp + ExpiringUploads.expireAfter,
      file: filename,
      hash: ExpiringUploads.getHash(data)
    };

    async.parallel({
      fs: function(next) {
        ExpiringUploads.saveFile(data.file.path, imgData.file, next);
      },
      db: function(next) {
        ExpiringUploads.writeToDB(imgData, next);
      }
    }, function(err) {
      if (err) {
        return cb(err);
      }
      cb(null, {
        url: nconf.get('upload_url') + imgData.hash + '/' + hexTstamp +
             '/' + data.file.name.toLowerCase(),
        name: data.file.name.toLowerCase()
      });
    });
  } else {
    ExpiringUploads.doStandard(data, cb);
  }
};

ExpiringUploads.getHash = function(imgData) {
  // key is generated from 'NodeBB secret'
  var key = nconf.get('secret');
  key = parseInt('0x' + key.substring(0, key.indexOf('-')), 16);
  return xxh.hash(new Buffer(JSON.stringify(imgData)), key).toString(16);
};

ExpiringUploads.doStandard = function(data, cb) {
  if (parseInt(meta.config.allowFileUploads, 10) !== 1) {
    return cb(new Error('[[error:uploads-are-disabled]]'));
  }

  if (!data.file) {
    return cb(new Error('[[error:invalid-file]]'));
  }

  if (data.file.size > parseInt(meta.config.maximumFileSize, 10) * 1024) {
    return cb(new Error('[[error:file-too-big, ' +
                        meta.config.maximumFileSize + ']]'));
  }

  var filename = data.file.name || 'upload';

  filename = Date.now() + '-' + validator.escape(filename).substr(0, 255);
  file.saveFileToLocal(filename, 'files', data.file.path,
                       function(err, upload) {
    if (err) {
      return cb(err);
    }
    cb(null, {
			url: nconf.get('relative_path') + upload.url,
      name: data.file.name
		});
  });
};

ExpiringUploads.saveFile = function(src, dest, cb) {
  var is = fs.createReadStream(src);
  var os = fs.createWriteStream(nconf.get('base_dir') +
                                ExpiringUploads.storage + dest);

  is.on('end', cb);
  os.on('error', cb);
  is.pipe(os);
};

ExpiringUploads.writeToDB = function(imgData, cb) {
  async.waterfall([
    function(next) {
      db.incrObjectField('settings:expiring-uploads', 'lastID', next);
    },
    function(id, next) {
      db.sortedSetAdd('expiring-uploads:ids', imgData.tstamp, id, function() {
        return next(null, id);
      });
    },
    function(id, next) {
      db.setObject('expiring-uploads:' + id, imgData, next);
    }
  ],
  function(err) {
    if (err) {
      return cb(err);
    }
  });
  return cb();
};

ExpiringUploads.resolveRequest = function(req, res, cb) {
  var hash = req.params.hash;
  // timestamp comes in as hex string
  var tstamp = parseInt('0x' + req.params.tstamp, 16);
  var fname = req.params.fname;

  // return when file (according to request url) is expired.
  // the url could be wrong, but then it's up for grabs, anyway :)
  if (Date.now() > tstamp + ExpiringUploads.expireAfter) {
    return ExpiringUploads.sendGone();
  }
  async.waterfall([
    function(next) {
      // get ID of upload
      db.getSortedSetRevRangeByScore('expiring-uploads:ids', 0, 1,
                                     tstamp, tstamp, next);
    },
    function(id, next) {
      if (id.length === 0) {
        return ExpiringUploads.sendGone(req, res);
      }
      // get upload info to perform checks
      db.getObjectFields('expiring-uploads:' + id[0],
                         ['hash', 'tstamp', 'file'], next);
    }], function(err, fields) {
      if (err) {
        return cb(err);
      }
      var hashMatch = (fields.hash === hash);
      var timeMatch = (parseInt(fields.tstamp, 10) === tstamp);
      var nameMatch = (fields.file === tstamp + '-' + fname);
      if (hashMatch && timeMatch && nameMatch) {
        res.status(200);
        // tell (not force! It's not part of the HTTP standard.) the browser
        // to download the file, even if it has a recognized/handled MIME.
        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1
        res.setHeader('Content-Disposition', 'attachement');
        res.sendFile(nconf.get('base_dir') + ExpiringUploads.storage +
                     fields.file);
      }
    });
};

ExpiringUploads.sendGone = function(req, res) {
  var mw = require.main.require('./src/middleware/middleware')(req.app);
  // 410 Gone
  // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.11
  res.status(410);
  mw.buildHeader(req, res, function() {
    // add custom template
    res.render('404', {path: res.path});
  });
};

ExpiringUploads.Admin.addMenuItem = function(custom_header, cb) {
  custom_header.plugins.push({
    route: '/plugins/expups',
    icon: 'fa-clock-o',
    name: 'ExpiringUploads'
  });
  cb(null, custom_header);
};

module.exports = ExpiringUploads;
<|endoftext|>


<commit_before>/*!
 * Bootstrap Grunt task for Glyphicons data generation
 * http://getbootstrap.com
 * Copyright 2014 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 */
'use strict';
var fs = require('fs');

module.exports = function generateGlyphiconsData() {
  // Pass encoding, utf8, so `readFileSync` will return a string instead of a
  // buffer
  var glyphiconsFile = fs.readFileSync('less/glyphicons.less', 'utf8');
  var glpyhiconsLines = glyphiconsFile.split('\n');

  // Use any line that starts with ".glyphicon-" and capture the class name
  var iconClassName = /^\.(glyphicon-[^\s]+)/;
  var glyphiconsData = '# This file is generated via Grunt task. **Do not edit directly.**\n' +
                       '# See the \'build-glyphicons-data\' task in Gruntfile.js.\n\n';
  for (var i = 0, len = glpyhiconsLines.length; i < len; i++) {
    var match = glpyhiconsLines[i].match(iconClassName);

    if (match !== null) {
      glyphiconsData += '- ' + match[1] + '\n';
    }
  }

  // Create the `_data` directory if it doesn't already exist
  if (!fs.existsSync('docs/_data')) {
    fs.mkdirSync('docs/_data');
  }

  fs.writeFileSync('docs/_data/glyphicons.yml', glyphiconsData);
};
<commit_msg>Fix typo.<commit_after>/*!
 * Bootstrap Grunt task for Glyphicons data generation
 * http://getbootstrap.com
 * Copyright 2014 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 */
'use strict';
var fs = require('fs');

module.exports = function generateGlyphiconsData() {
  // Pass encoding, utf8, so `readFileSync` will return a string instead of a
  // buffer
  var glyphiconsFile = fs.readFileSync('less/glyphicons.less', 'utf8');
  var glyphiconsLines = glyphiconsFile.split('\n');

  // Use any line that starts with ".glyphicon-" and capture the class name
  var iconClassName = /^\.(glyphicon-[^\s]+)/;
  var glyphiconsData = '# This file is generated via Grunt task. **Do not edit directly.**\n' +
                       '# See the \'build-glyphicons-data\' task in Gruntfile.js.\n\n';
  for (var i = 0, len = glyphiconsLines.length; i < len; i++) {
    var match = glyphiconsLines[i].match(iconClassName);

    if (match !== null) {
      glyphiconsData += '- ' + match[1] + '\n';
    }
  }

  // Create the `_data` directory if it doesn't already exist
  if (!fs.existsSync('docs/_data')) {
    fs.mkdirSync('docs/_data');
  }

  fs.writeFileSync('docs/_data/glyphicons.yml', glyphiconsData);
};
<|endoftext|>


<commit_before>let focused      = 0
  , isFullScreen = false
  , videos       = document.getElementsByTagName("video") //htmlCollection
    videos       = [].slice.call(videos);                  //Array

videos[0].playbackRate = 1.8;

// focus listener
document.addEventListener('click', (event) => {
  let e = event.target;
  if (e.tagName != 'VIDEO') {
    focused = -1;
    return;
  }
  // else: video clicked, but which one?
  focused = videos.findIndex((event) => {
    return event.id == e.id;
  })
  //event.preventDefault()
  //togglePause(videos[focused])
});

// keyboard shortcuts listener
document.addEventListener('keydown', (event) => {
  if (focused == -1){
    return;
  }
  event.preventDefault()
  let key = event.code;
  // else: video focused
  switch(key) {
    case 'Space':
    case 'KeyK':
    case 'KeyS':
      togglePause(videos[focused])
      break;
    case 'ArrowLeft':
    case 'KeyA':
      videos[focused].currentTime -= 5;
      break;
    case 'ArrowRight':
    case 'KeyD':
      videos[focused].currentTime += 5;
      break;
    case 'ArrowUp':
      videos[focused].volume *= 1.25;
      break;
    case 'ArrowDown':
      videos[focused].volume /= 1.25;
      break;
    case 'KeyJ':
      videos[focused].currentTime -= 10;
      break;
    case 'KeyL':
      videos[focused].currentTime += 10;
      break;
    case 'KeyF':
      toggleFullScreen(videos[focused]);
      break;
    case 'Escape':
      exitFullScreen(videos[focused]);
      break;
    case 'Comma':
      videos[focused].playbackRate /= 1.1;
      console.log(videos[focused].playbackRate);
      break;
    case 'Period':
      videos[focused].playbackRate *= 1.1;
      console.log(videos[focused].playbackRate);
      break;
  }
})

let togglePause = (v) => {
  if (v.paused){
    v.play();
  } else {
    v.pause();
  }
}

let toggleFullScreen = (v) => {
  // firefox
  if (v.mozRequestFullScreen) {
    if (isFullScreen) {
      exitFullScreen(v);
    } else {
      v.mozRequestFullScreen();
    }
  }
  // chrome
  else // if (v.webkitRequestFullScreen)
  {
    if (isFullScreen) {
      exitFullScreen(v);
    } else{
      v.webkitRequestFullScreen();
    }
  }
}

let exitFullScreen = (v) => {
  if (v.exitFullscreen) {
    v.exitFullscreen();
  } else if (v.mozCancelFullScreen) {
    v.mozCancelFullScreen();
  } else if (v.webkitExitFullscreen) {
    v.webkitExitFullscreen();
  }
}

/* fullscreen */
document.addEventListener("fullscreenchange", () => {
    isFullScreen = !isFullScreen;
}, false);

document.addEventListener("mozfullscreenchange", () => {
    isFullScreen = !isFullScreen;
}, false);

document.addEventListener("webkitfullscreenchange", () => {
    isFullScreen = !isFullScreen;
}, false);

document.addEventListener("msfullscreenchange", () => {
    isFullScreen = !isFullScreen;
}, false);
<commit_msg>Allman to k&R style<commit_after>let focused      = 0
  , isFullScreen = false
  , videos       = document.getElementsByTagName("video") //htmlCollection
    videos       = [].slice.call(videos);                  //Array

videos[0].playbackRate = 1.8;

// focus listener
document.addEventListener('click', (event) => {
  let e = event.target;
  if (e.tagName != 'VIDEO') {
    focused = -1;
    return;
  }
  // else: video clicked, but which one?
  focused = videos.findIndex((event) => {
    return event.id == e.id;
  })
  //event.preventDefault()
  //togglePause(videos[focused])
});

// keyboard shortcuts listener
document.addEventListener('keydown', (event) => {
  if (focused == -1) {
    return;
  }
  event.preventDefault();
  let key = event.code;
  // else: video focused
  switch(key) {
    case 'Space':
    case 'KeyK':
    case 'KeyS':
      togglePause(videos[focused])
      break;
    case 'ArrowLeft':
    case 'KeyA':
      videos[focused].currentTime -= 5;
      break;
    case 'ArrowRight':
    case 'KeyD':
      videos[focused].currentTime += 5;
      break;
    case 'ArrowUp':
      videos[focused].volume *= 1.25;
      break;
    case 'ArrowDown':
      videos[focused].volume /= 1.25;
      break;
    case 'KeyJ':
      videos[focused].currentTime -= 10;
      break;
    case 'KeyL':
      videos[focused].currentTime += 10;
      break;
    case 'KeyF':
      toggleFullScreen(videos[focused]);
      break;
    case 'Escape':
      exitFullScreen(videos[focused]);
      break;
    case 'Comma':
      videos[focused].playbackRate /= 1.1;
      console.log(videos[focused].playbackRate);
      break;
    case 'Period':
      videos[focused].playbackRate *= 1.1;
      console.log(videos[focused].playbackRate);
      break;
  }
})

let togglePause = (v) => {
  if (v.paused) {
    v.play();
  } else {
    v.pause();
  }
}

let toggleFullScreen = (v) => {
  // firefox
  if (v.mozRequestFullScreen) {
    if (isFullScreen) {
      exitFullScreen(v);
    } else {
      v.mozRequestFullScreen();
    }
  }
  // chrome
  else // if (v.webkitRequestFullScreen)
  {
    if (isFullScreen) {
      exitFullScreen(v);
    } else {
      v.webkitRequestFullScreen();
    }
  }
}

let exitFullScreen = (v) => {
  if (v.exitFullscreen) {
    v.exitFullscreen();
  } else if (v.mozCancelFullScreen) {
    v.mozCancelFullScreen();
  } else if (v.webkitExitFullscreen) {
    v.webkitExitFullscreen();
  }
}

/* fullscreen */
document.addEventListener("fullscreenchange", () => {
    isFullScreen = !isFullScreen;
}, false);

document.addEventListener("mozfullscreenchange", () => {
    isFullScreen = !isFullScreen;
}, false);

document.addEventListener("webkitfullscreenchange", () => {
    isFullScreen = !isFullScreen;
}, false);

document.addEventListener("msfullscreenchange", () => {
    isFullScreen = !isFullScreen;
}, false);
<|endoftext|>


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

    var _gameEngine = null;
    var _EventSettings = null;
    var _startGameSound = null;
    var _backgroundThemeSong = null;
    var _isIE = null;

    // Constructor
    function EventListener(gameEngine, EventSettings) {
        _gameEngine = gameEngine;
        _EventSettings = EventSettings;
        _startGameSound = new Audio(_EventSettings.startGameSoundSrc);
        _backgroundThemeSong = new Audio(_EventSettings.gameThemeSong);
        _isIE = detectIE();
    }

    /// <summary>
    /// When some of the start buttons is clicked - starts the game if it is not started already
    /// </summary>
    function startGame() {
        if (!_gameEngine.isRunning()) {
            _gameEngine.startGame();

            if (_isIE) {
                playMusicOnOldBrowsers(_EventSettings.startGameSoundSrc);
                playMusicOnOldBrowsers(_EventSettings.gameThemeSong);
            } else {
                _startGameSound.play();
                loopMusic(_backgroundThemeSong);
            }
        }
    }

    function loopMusic(musicElement) {
        musicElement.addEventListener('ended', function () {
            this.currentTime = 0;
            this.play();
        }, false);

        musicElement.play();
    }

    function playMusicOnOldBrowsers(src) {
        $('<object/>')
            .attr('data', src)
            .attr('type', 'audio/' + src.split('.').pop())
            .hide()
            .append($('<embed/>').attr('src', src))
            .appendTo('body');
    }

    function detectIE() {
        var userAgent = window.navigator.userAgent;
        var msie = userAgent.indexOf('MSIE');
        var ie11 = userAgent.indexOf('Trident');
        var isIE = msie > 0 || ie11 > 0;
        return isIE;
    }

    /// <summary>
    /// Resize html elements containers and show/hide fullscreen buttons
    /// </summary>
    function resizeFieldOnToggleFullScreenMode(sender, btnIdToShow, isInFC) {
        $(_EventSettings.gameFieldId).css('padding-top', isInFC ? '240px' : '0');
        $(_EventSettings.backgroundLayerId).css('margin-top', isInFC ? '-120px' : '');
        $(_EventSettings.playerLayerId).css('margin-top', isInFC ? '-240px' : '');
        $('html').css('height', isInFC ? '100%' : '');
        $('body').css('height', isInFC ? '100%' : '');
        $(btnIdToShow).show();
        $(sender).hide();
    }

    /// <summary>
    /// Toggle fullscreen for browsers that support it!
    /// </summary>
    function tryToggleFullscreenMode() {
        var docElement = document.documentElement;
        var request = docElement.requestFullscreen || docElement.webkitRequestFullScreen || docElement.mozRequestFullScreen || docElement.msRequestFullscreen;

        if (typeof request != "undefined" && request) {
            request.call(docElement);
            return true;
        }

        return false;
    }

    /// <summary>
    /// Cancel fullscreen for browsers that support it!
    /// </summary>
    function tryExitFullscreen() {
        var docElement = document;
        var request = docElement.exitFullScreen || docElement.mozCancelFullScreen || docElement.webkitExitFullScreen || docElement.webkitCancelFullScreen || docElement.msCancelFullscreen || docElement.msExitFullscreen;

        if (typeof request != "undefined" && request) {
            request.call(docElement);
            return true;
        }

        return false;
    }

    // Public function
    EventListener.prototype.setButtonEvents = function (gameEngine) {
        // On Start button click - starts the game
        $(_EventSettings.startGameButtonId).on('click', function () {
            startGame();
            $('#start').hide();
        });

        // Start fullscreen mode Button
        $(_EventSettings.toggleFullscreenButtonId).on('click', function () {
            if (tryToggleFullscreenMode()) {
                resizeFieldOnToggleFullScreenMode($(this), _EventSettings.exitFullscreenButtonId, true);
            }

            //startGame();

        });

        // Exit from fullscreen mode Button
        $(_EventSettings.exitFullscreenButtonId).on('click', function () {
            if (tryExitFullscreen()) {
                resizeFieldOnToggleFullScreenMode($(this), _EventSettings.toggleFullscreenButtonId, false);
            }
        });
    };

    return EventListener;
});<commit_msg>rediced theme song volume so that salsh sound could be heared more clearly<commit_after>define(function (require) {
    'use strict';

    var _gameEngine = null;
    var _EventSettings = null;
    var _startGameSound = null;
    var _backgroundThemeSong = null;
    var _isIE = null;

    // Constructor
    function EventListener(gameEngine, EventSettings) {
        _gameEngine = gameEngine;
        _EventSettings = EventSettings;
        _startGameSound = new Audio(_EventSettings.startGameSoundSrc);
        _startGameSound.volume = 1;
        _backgroundThemeSong = new Audio(_EventSettings.gameThemeSong);
        _backgroundThemeSong.volume = 0.8;
        _isIE = detectIE();
    }

    /// <summary>
    /// When some of the start buttons is clicked - starts the game if it is not started already
    /// </summary>
    function startGame() {
        if (!_gameEngine.isRunning()) {
            _gameEngine.startGame();

            if (_isIE) {
                playMusicOnOldBrowsers(_EventSettings.startGameSoundSrc);
                playMusicOnOldBrowsers(_EventSettings.gameThemeSong);
            } else {
                _startGameSound.play();
                loopMusic(_backgroundThemeSong);
            }
        }
    }

    function loopMusic(musicElement) {
        musicElement.addEventListener('ended', function () {
            this.currentTime = 0;
            this.play();
        }, false);

        musicElement.play();
    }

    function playMusicOnOldBrowsers(src) {
        $('<object/>')
            .attr('data', src)
            .attr('type', 'audio/' + src.split('.').pop())
            .hide()
            .append($('<embed/>').attr('src', src))
            .appendTo('body');
    }

    function detectIE() {
        var userAgent = window.navigator.userAgent;
        var msie = userAgent.indexOf('MSIE');
        var ie11 = userAgent.indexOf('Trident');
        var isIE = msie > 0 || ie11 > 0;
        return isIE;
    }

    /// <summary>
    /// Resize html elements containers and show/hide fullscreen buttons
    /// </summary>
    function resizeFieldOnToggleFullScreenMode(sender, btnIdToShow, isInFC) {
        $(_EventSettings.gameFieldId).css('padding-top', isInFC ? '240px' : '0');
        $(_EventSettings.backgroundLayerId).css('margin-top', isInFC ? '-120px' : '');
        $(_EventSettings.playerLayerId).css('margin-top', isInFC ? '-240px' : '');
        $('html').css('height', isInFC ? '100%' : '');
        $('body').css('height', isInFC ? '100%' : '');
        $(btnIdToShow).show();
        $(sender).hide();
    }

    /// <summary>
    /// Toggle fullscreen for browsers that support it!
    /// </summary>
    function tryToggleFullscreenMode() {
        var docElement = document.documentElement;
        var request = docElement.requestFullscreen || docElement.webkitRequestFullScreen || docElement.mozRequestFullScreen || docElement.msRequestFullscreen;

        if (typeof request != "undefined" && request) {
            request.call(docElement);
            return true;
        }

        return false;
    }

    /// <summary>
    /// Cancel fullscreen for browsers that support it!
    /// </summary>
    function tryExitFullscreen() {
        var docElement = document;
        var request = docElement.exitFullScreen || docElement.mozCancelFullScreen || docElement.webkitExitFullScreen || docElement.webkitCancelFullScreen || docElement.msCancelFullscreen || docElement.msExitFullscreen;

        if (typeof request != "undefined" && request) {
            request.call(docElement);
            return true;
        }

        return false;
    }

    // Public function
    EventListener.prototype.setButtonEvents = function (gameEngine) {
        // On Start button click - starts the game
        $(_EventSettings.startGameButtonId).on('click', function () {
            startGame();
            $('#start').hide();
        });

        // Start fullscreen mode Button
        $(_EventSettings.toggleFullscreenButtonId).on('click', function () {
            if (tryToggleFullscreenMode()) {
                resizeFieldOnToggleFullScreenMode($(this), _EventSettings.exitFullscreenButtonId, true);
            }

            //startGame();

        });

        // Exit from fullscreen mode Button
        $(_EventSettings.exitFullscreenButtonId).on('click', function () {
            if (tryExitFullscreen()) {
                resizeFieldOnToggleFullScreenMode($(this), _EventSettings.toggleFullscreenButtonId, false);
            }
        });
    };

    return EventListener;
});
<|endoftext|>