<commit_before>// Adapter for testharness.js-style tests with Service Workers

// Can only be used with a worker that installs successfully, since it
// first registers to acquire a ServiceWorkerRegistration object to
// unregister.
// FIXME: Use getRegistration() when implemented.
function service_worker_unregister_and_register(test, url, scope) {
  if (!scope || scope.length == 0)
    return Promise.reject(new Error('tests must define a scope'));

  var options = { scope: scope };
  return navigator.serviceWorker.register(url, options)
      .then(function(registration) {
          return registration.unregister();
        })
      .then(function() {
          return navigator.serviceWorker.register(url, options);
        })
      .catch(unreached_rejection(test,
                                 'unregister and register should not fail'));
}

function service_worker_unregister_and_done(test, scope) {
    return navigator.serviceWorker.unregister(scope).then(
        test.done.bind(test),
        unreached_rejection(test, 'unregister should not fail'));
}

// Rejection-specific helper that provides more details
function unreached_rejection(test, prefix) {
    return test.step_func(function(error) {
        var reason = error.message || error.name || error;
        var error_prefix = prefix || 'unexpected rejection';
        assert_unreached(error_prefix + ': ' + reason);
    });
}

// FIXME: Clean up the iframe when the test completes.
function with_iframe(url, f) {
    return new Promise(function(resolve, reject) {
        var frame = document.createElement('iframe');
        frame.src = url;
        frame.onload = function() {
            if (f) {
              f(frame);
            }
            resolve(frame);
        };
        document.body.appendChild(frame);
    });
}

function unload_iframe(iframe) {
  var saw_unload = new Promise(function(resolve) {
      iframe.contentWindow.addEventListener('unload', function() {
          resolve();
        });
    });
  iframe.src = '';
  iframe.remove();
  return saw_unload;
}

function normalizeURL(url) {
  return new URL(url, document.location).toString().replace(/#.*$/, '');
}

function wait_for_update(test, registration) {
  if (!registration || registration.unregister == undefined) {
    return Promise.reject(new Error(
        'wait_for_update must be passed a ServiceWorkerRegistration'));
  }

  return new Promise(test.step_func(function(resolve) {
      registration.addEventListener('updatefound', test.step_func(function() {
          resolve(registration.installing);
      }));
    }));
}

function wait_for_state(test, worker, state) {
  if (!worker || worker.state == undefined) {
    return Promise.reject(new Error(
        'wait_for_state must be passed a ServiceWorker'));
  }

  return new Promise(test.step_func(function(resolve) {
      worker.addEventListener('statechange', test.step_func(function() {
          if (worker.state === state)
            resolve(state);
        }));
    }));
}

function wait_for_activated(test, registration) {
  var expected_state = 'activated';
  if (registration.active) {
    if (registration.active.state === expected_state)
      return Promise.resolve(registration.active);
    else
      return wait_for_state(test, registration.active, expected_state);
  }
  if (registration.waiting)
    return wait_for_state(test, registration.waiting, expected_state);
  if (registration.installing)
    return wait_for_state(test, registration.installing, expected_state);
  return Promise.reject(
      new Error('registration must have at least one version'));
}

(function() {
  function fetch_tests_from_worker(worker) {
    return new Promise(function(resolve, reject) {
        var messageChannel = new MessageChannel();
        messageChannel.port1.addEventListener('message', function(message) {
            if (message.data.type == 'complete') {
              synthesize_tests(message.data.tests, message.data.status);
              resolve();
            }
          });
        worker.postMessage({type: 'fetch_results', port: messageChannel.port2},
                           [messageChannel.port2]);
        messageChannel.port1.start();
      });
  };

  function synthesize_tests(tests, status) {
    for (var i = 0; i < tests.length; ++i) {
      var t = async_test(tests[i].name);
      switch (tests[i].status) {
        case tests[i].PASS:
          t.step(function() { assert_true(true); });
          t.done();
          break;
        case tests[i].TIMEOUT:
          t.force_timeout();
          break;
        case tests[i].FAIL:
          t.step(function() { throw {message: tests[i].message}; });
          break;
        case tests[i].NOTRUN:
          // Leave NOTRUN alone. It'll get marked as a NOTRUN when the test
          // terminates.
          break;
      }
    }
  };

  function service_worker_test(url, description) {
    var scope = window.location.origin + '/service-worker-scope/' +
      window.location.pathname;

    var test = async_test(description);
    service_worker_unregister_and_register(test, url, scope)
      .then(function(registration) {
          return wait_for_update(test, registration);
        })
      .then(function(worker) { return fetch_tests_from_worker(worker); })
      .then(function() { return navigator.serviceWorker.unregister(scope); })
      .then(function() { test.done(); })
      .catch(test.step_func(function(e) { throw e; }));
  };

  self.service_worker_test = service_worker_test;
})();

function get_host_info() {
    var ORIGINAL_HOST = '127.0.0.1';
    var REMOTE_HOST = 'localhost';
    var UNAUTHENTICATED_HOST = 'example.test';
    var HTTP_PORT = 8000;
    var HTTPS_PORT = 8443;
    try {
        // In W3C test, we can get the hostname and port number in config.json
        // using wptserve's built-in pipe.
        // http://wptserve.readthedocs.org/en/latest/pipes.html#built-in-pipes
        HTTP_PORT = eval('{{ports[http][0]}}');
        HTTPS_PORT = eval('{{ports[https][0]}}');
        ORIGINAL_HOST = eval('\'{{host}}\'');
        REMOTE_HOST = 'www1.' + ORIGINAL_HOST;
    } catch(e) {
    }
    return {
        HTTP_ORIGIN: 'http://' + ORIGINAL_HOST + ':' + HTTP_PORT,
        HTTPS_ORIGIN: 'https://' + ORIGINAL_HOST + ':' + HTTPS_PORT,
        HTTP_REMOTE_ORIGIN: 'http://' + REMOTE_HOST + ':' + HTTP_PORT,
        HTTPS_REMOTE_ORIGIN: 'https://' + REMOTE_HOST + ':' + HTTPS_PORT,
        UNAUTHENTICATED_ORIGIN: 'http://' + UNAUTHENTICATED_HOST + ':' + HTTP_PORT
    };
}

function base_path() {
    return location.pathname.replace(/\/[^\/]*$/, '/');
}
<commit_msg>ServiceWorker: Stabilize wait_for_state() helper<commit_after>// Adapter for testharness.js-style tests with Service Workers

// Can only be used with a worker that installs successfully, since it
// first registers to acquire a ServiceWorkerRegistration object to
// unregister.
// FIXME: Use getRegistration() when implemented.
function service_worker_unregister_and_register(test, url, scope) {
  if (!scope || scope.length == 0)
    return Promise.reject(new Error('tests must define a scope'));

  var options = { scope: scope };
  return navigator.serviceWorker.register(url, options)
      .then(function(registration) {
          return registration.unregister();
        })
      .then(function() {
          return navigator.serviceWorker.register(url, options);
        })
      .catch(unreached_rejection(test,
                                 'unregister and register should not fail'));
}

function service_worker_unregister_and_done(test, scope) {
    return navigator.serviceWorker.unregister(scope).then(
        test.done.bind(test),
        unreached_rejection(test, 'unregister should not fail'));
}

// Rejection-specific helper that provides more details
function unreached_rejection(test, prefix) {
    return test.step_func(function(error) {
        var reason = error.message || error.name || error;
        var error_prefix = prefix || 'unexpected rejection';
        assert_unreached(error_prefix + ': ' + reason);
    });
}

// FIXME: Clean up the iframe when the test completes.
function with_iframe(url, f) {
    return new Promise(function(resolve, reject) {
        var frame = document.createElement('iframe');
        frame.src = url;
        frame.onload = function() {
            if (f) {
              f(frame);
            }
            resolve(frame);
        };
        document.body.appendChild(frame);
    });
}

function unload_iframe(iframe) {
  var saw_unload = new Promise(function(resolve) {
      iframe.contentWindow.addEventListener('unload', function() {
          resolve();
        });
    });
  iframe.src = '';
  iframe.remove();
  return saw_unload;
}

function normalizeURL(url) {
  return new URL(url, document.location).toString().replace(/#.*$/, '');
}

function wait_for_update(test, registration) {
  if (!registration || registration.unregister == undefined) {
    return Promise.reject(new Error(
        'wait_for_update must be passed a ServiceWorkerRegistration'));
  }

  return new Promise(test.step_func(function(resolve) {
      registration.addEventListener('updatefound', test.step_func(function() {
          resolve(registration.installing);
      }));
    }));
}

function wait_for_state(test, worker, state) {
  if (!worker || worker.state == undefined) {
    return Promise.reject(new Error(
        'wait_for_state must be passed a ServiceWorker'));
  }
  if (worker.state === state)
    return Promise.resolve(state);

  if (state === 'installing') {
    switch (worker.state) {
    case 'installed':
    case 'activating':
    case 'activated':
    case 'redundant':
      return Promise.reject(new Error(
          'worker is ' + worker.state + ' but waiting for ' + state));
    }
  }

  if (state === 'installed') {
    switch (worker.state) {
    case 'activating':
    case 'activated':
    case 'redundant':
      return Promise.reject(new Error(
          'worker is ' + worker.state + ' but waiting for ' + state));
    }
  }

  if (state === 'activating') {
    switch (worker.state) {
    case 'activated':
    case 'redundant':
      return Promise.reject(new Error(
          'worker is ' + worker.state + ' but waiting for ' + state));
    }
  }

  if (state === 'activated') {
    switch (worker.state) {
    case 'redundant':
      return Promise.reject(new Error(
          'worker is ' + worker.state + ' but waiting for ' + state));
    }
  }

  return new Promise(test.step_func(function(resolve) {
      worker.addEventListener('statechange', test.step_func(function() {
          if (worker.state === state)
            resolve(state);
        }));
    }));
}

function wait_for_activated(test, registration) {
  var expected_state = 'activated';
  if (registration.active)
    return wait_for_state(test, registration.active, expected_state);
  if (registration.waiting)
    return wait_for_state(test, registration.waiting, expected_state);
  if (registration.installing)
    return wait_for_state(test, registration.installing, expected_state);
  return Promise.reject(
      new Error('registration must have at least one version'));
}

(function() {
  function fetch_tests_from_worker(worker) {
    return new Promise(function(resolve, reject) {
        var messageChannel = new MessageChannel();
        messageChannel.port1.addEventListener('message', function(message) {
            if (message.data.type == 'complete') {
              synthesize_tests(message.data.tests, message.data.status);
              resolve();
            }
          });
        worker.postMessage({type: 'fetch_results', port: messageChannel.port2},
                           [messageChannel.port2]);
        messageChannel.port1.start();
      });
  };

  function synthesize_tests(tests, status) {
    for (var i = 0; i < tests.length; ++i) {
      var t = async_test(tests[i].name);
      switch (tests[i].status) {
        case tests[i].PASS:
          t.step(function() { assert_true(true); });
          t.done();
          break;
        case tests[i].TIMEOUT:
          t.force_timeout();
          break;
        case tests[i].FAIL:
          t.step(function() { throw {message: tests[i].message}; });
          break;
        case tests[i].NOTRUN:
          // Leave NOTRUN alone. It'll get marked as a NOTRUN when the test
          // terminates.
          break;
      }
    }
  };

  function service_worker_test(url, description) {
    var scope = window.location.origin + '/service-worker-scope/' +
      window.location.pathname;

    var test = async_test(description);
    service_worker_unregister_and_register(test, url, scope)
      .then(function(registration) {
          return wait_for_update(test, registration);
        })
      .then(function(worker) { return fetch_tests_from_worker(worker); })
      .then(function() { return navigator.serviceWorker.unregister(scope); })
      .then(function() { test.done(); })
      .catch(test.step_func(function(e) { throw e; }));
  };

  self.service_worker_test = service_worker_test;
})();

function get_host_info() {
    var ORIGINAL_HOST = '127.0.0.1';
    var REMOTE_HOST = 'localhost';
    var UNAUTHENTICATED_HOST = 'example.test';
    var HTTP_PORT = 8000;
    var HTTPS_PORT = 8443;
    try {
        // In W3C test, we can get the hostname and port number in config.json
        // using wptserve's built-in pipe.
        // http://wptserve.readthedocs.org/en/latest/pipes.html#built-in-pipes
        HTTP_PORT = eval('{{ports[http][0]}}');
        HTTPS_PORT = eval('{{ports[https][0]}}');
        ORIGINAL_HOST = eval('\'{{host}}\'');
        REMOTE_HOST = 'www1.' + ORIGINAL_HOST;
    } catch(e) {
    }
    return {
        HTTP_ORIGIN: 'http://' + ORIGINAL_HOST + ':' + HTTP_PORT,
        HTTPS_ORIGIN: 'https://' + ORIGINAL_HOST + ':' + HTTPS_PORT,
        HTTP_REMOTE_ORIGIN: 'http://' + REMOTE_HOST + ':' + HTTP_PORT,
        HTTPS_REMOTE_ORIGIN: 'https://' + REMOTE_HOST + ':' + HTTPS_PORT,
        UNAUTHENTICATED_ORIGIN: 'http://' + UNAUTHENTICATED_HOST + ':' + HTTP_PORT
    };
}

function base_path() {
    return location.pathname.replace(/\/[^\/]*$/, '/');
}
<|endoftext|>


<commit_before>import { Promise } from './concurrency-helpers';

function isPromise(thing) {
  return thing && typeof thing.then === 'function';
}

function wake(entry, resolved, onError) {
 try {
    if (resolved.state === 'fulfilled') {
      entry.intermediate = entry.generator.next(resolved.value);
    } else {
      entry.intermediate = entry.generator.throw(resolved.reason);
    }
 } catch(err) {
   entry.intermediate = {
     done: true
   };
   if (onError) {
     onError(err);
   }
 }
}

function cancelGenerator(generator) {
  let e = new Error('TaskCancelation');
  e.message = 'TaskCancelation';
  try {
    generator.throw(e);
  } catch(err) {
    if (err.message !== 'TaskCancelation') {
      throw err;
    }
  }
}

function cancel() {
  let waiting = this.__ea_waiting__.waiting;
  if (!waiting) { return; }
  for (let i = 0; i < waiting.length; i++) {
    let entry = waiting[i];
    let value = entry.intermediate.value;
    if (isPromise(value) && value.__ec_cancel__) {
      value.__ec_cancel__();
    }
    cancelGenerator(entry.generator);
  }
}

function race(waiting) {
  let bucket = { waiting };
  let p = new Promise(resolve => {
    for (let index = 0; index < waiting.length; index++) {
      let entry = waiting[index];
      let value = entry.intermediate.value;
      Promise.resolve(value).then(value => {
        bucket.waiting = null;
        resolve({ state: 'fulfilled', value, index });
      }, reason => {
        bucket.waiting = null;
        resolve({ state: 'rejected', reason, index });
      });
    }
  });
  p.__ec_cancel__ = cancel;
  p.__ea_waiting__ = bucket;
  return p;
}

export default function * parallel(generators, onError) {
  let waiting = [];

  for (let i = 0; i < generators.length; i++) {
    let generator = generators[i];
    let entry = { generator };
    wake(entry, { state: 'fulfilled' }, onError);
    if (!entry.intermediate.done) {
      waiting.push(entry)
    }
  }

  while (waiting.length > 0) {
    let resolved = yield race(waiting);
    let { index } = resolved;
    let entry = waiting[index];
    waiting.splice(index, 1);

    // This condition is needed because we wait for both non-done
    // generators and done generators that returned a final promise.
    if (!entry.intermediate.done) {
      wake(entry, resolved, onError);
      if (!entry.intermediate.done || isPromise(entry.intermediate.value)) {
        // we keep waiting if the generator isn't done *or* if the
        // final return value was a promise.
        waiting.push(entry);
      }
    }
  }
}
<commit_msg>oops, this was silly. Fixed.<commit_after>import { Promise } from './concurrency-helpers';

function isPromise(thing) {
  return thing && typeof thing.then === 'function';
}

function wake(entry, resolved, onError) {
 try {
    if (resolved.state === 'fulfilled') {
      entry.intermediate = entry.generator.next(resolved.value);
    } else {
      entry.intermediate = entry.generator.throw(resolved.reason);
    }
 } catch(err) {
   entry.intermediate = {
     done: true
   };
   if (onError) {
     onError(err);
   }
 }
}

function cancelGenerator(generator) {
  let e = new Error('TaskCancelation');
  e.message = 'TaskCancelation';
  try {
    generator.throw(e);
  } catch(err) {
    if (err.message !== 'TaskCancelation') {
      throw err;
    }
  }
}

function cancel(waiting) {
  if (!waiting) { return; }
  for (let i = 0; i < waiting.length; i++) {
    let entry = waiting[i];
    let value = entry.intermediate.value;
    if (isPromise(value) && value.__ec_cancel__) {
      value.__ec_cancel__();
    }
    cancelGenerator(entry.generator);
  }
}

function race(waiting) {
  let p = new Promise(resolve => {
    for (let index = 0; index < waiting.length; index++) {
      let entry = waiting[index];
      let value = entry.intermediate.value;
      Promise.resolve(value).then(value => {
        waiting = null;
        resolve({ state: 'fulfilled', value, index });
      }, reason => {
        waiting = null;
        resolve({ state: 'rejected', reason, index });
      });
    }
  });
  p.__ec_cancel__ = () => cancel(waiting);
  return p;
}

export default function * parallel(generators, onError) {
  let waiting = [];

  for (let i = 0; i < generators.length; i++) {
    let generator = generators[i];
    let entry = { generator };
    wake(entry, { state: 'fulfilled' }, onError);
    if (!entry.intermediate.done) {
      waiting.push(entry)
    }
  }

  while (waiting.length > 0) {
    let resolved = yield race(waiting);
    let { index } = resolved;
    let entry = waiting[index];
    waiting.splice(index, 1);

    // This condition is needed because we wait for both non-done
    // generators and done generators that returned a final promise.
    if (!entry.intermediate.done) {
      wake(entry, resolved, onError);
      if (!entry.intermediate.done || isPromise(entry.intermediate.value)) {
        // we keep waiting if the generator isn't done *or* if the
        // final return value was a promise.
        waiting.push(entry);
      }
    }
  }
}
<|endoftext|>


<commit_before>( function( vui ) {

	// Check if the provided vui global is defined, otherwise try to require it if
	// we're in a CommonJS environment; otherwise we'll just fail out
	if( vui === undefined ) {
		if( typeof require === 'function' ) {
			vui = require('../../core');
		} else {
			throw new Error('load vui first');
		}
	}

	// Export the vui object if we're in a CommonJS environment.
	// It will already be on the window otherwise
	if( typeof module === 'object' && typeof module.exports === 'object' ) {
		module.exports = vui;
	}

	var $ = vui.$;

	$.widget( "vui.vui_autoresize", {

		options: {
			MaxHeight: 'none',
			MinHeight: '20px'
		},

		_create: function () {
			var self = this;

			var textarea = $(this.element),
				minHeight = textarea.attr('data-autoresize-minheight') ||
					textarea.css('min-height') !== 'none' && textarea.css('min-height') ||
					this.options.MinHeight,
				maxHeight = textarea.attr('data-autoresize-maxheight') ||
					textarea.css('max-height') !== 'none' && textarea.css('max-height') ||
					this.options.MaxHeight;

			// normalize height values by setting and retrieving them on the element
			if (maxHeight !== 'none') {
				textarea[0].style.height = maxHeight;
				maxHeight = textarea.height();
			}

			textarea[0].style.height = minHeight;
			minHeight = textarea.height();

			// bind the adjust function with all values
			var populatedAdjust = !!Function.prototype.bind ?
				this._textAreaAdjust.bind(this, textarea, minHeight, maxHeight) :
				function () {
					self._textAreaAdjust(textarea, minHeight, maxHeight);
				};

			textarea.keyup(populatedAdjust);
			textarea.change(populatedAdjust);

			textarea.css('overflow-y', 'hidden');

			populatedAdjust();
		},

		_textAreaAdjust: function (textarea, minHeight, maxHeight) {
			var padding = textarea.innerHeight() - textarea.height();

			textarea
				.height(minHeight);

			var currentHeight = textarea[0].scrollHeight - padding;

			var setHeight = Math.max(minHeight, currentHeight);
			if (maxHeight !== 'none') {
				setHeight = setHeight > maxHeight ? maxHeight : setHeight;
			}

			textarea
				.height(setHeight)
				.css('overflow-y', setHeight === maxHeight ? 'auto' : 'hidden')
				.trigger('vui-autoresize-change');
		}

	} );

	vui.addClassInitializer(
		'vui-autoresize',
		function( node ) {
			$( node ).vui_autoresize();
		}
	);

} )( window.vui );
<commit_msg>(autoresize) switch to less verbose data attributes<commit_after>( function( vui ) {

	// Check if the provided vui global is defined, otherwise try to require it if
	// we're in a CommonJS environment; otherwise we'll just fail out
	if( vui === undefined ) {
		if( typeof require === 'function' ) {
			vui = require('../../core');
		} else {
			throw new Error('load vui first');
		}
	}

	// Export the vui object if we're in a CommonJS environment.
	// It will already be on the window otherwise
	if( typeof module === 'object' && typeof module.exports === 'object' ) {
		module.exports = vui;
	}

	var $ = vui.$;

	$.widget( "vui.vui_autoresize", {

		options: {
			MaxHeight: 'none',
			MinHeight: '20px'
		},

		_create: function () {
			var self = this;

			var textarea = $(this.element),
				minHeight = textarea.attr('data-min-height') ||
					textarea.css('min-height') !== 'none' && textarea.css('min-height') ||
					this.options.MinHeight,
				maxHeight = textarea.attr('data-max-height') ||
					textarea.css('max-height') !== 'none' && textarea.css('max-height') ||
					this.options.MaxHeight;

			// normalize height values by setting and retrieving them on the element
			if (maxHeight !== 'none') {
				textarea[0].style.height = maxHeight;
				maxHeight = textarea.height();
			}

			textarea[0].style.height = minHeight;
			minHeight = textarea.height();

			// bind the adjust function with all values
			var populatedAdjust = !!Function.prototype.bind ?
				this._textAreaAdjust.bind(this, textarea, minHeight, maxHeight) :
				function () {
					self._textAreaAdjust(textarea, minHeight, maxHeight);
				};

			textarea.keyup(populatedAdjust);
			textarea.change(populatedAdjust);

			textarea.css('overflow-y', 'hidden');

			populatedAdjust();
		},

		_textAreaAdjust: function (textarea, minHeight, maxHeight) {
			var padding = textarea.innerHeight() - textarea.height();

			textarea
				.height(minHeight);

			var currentHeight = textarea[0].scrollHeight - padding;

			var setHeight = Math.max(minHeight, currentHeight);
			if (maxHeight !== 'none') {
				setHeight = setHeight > maxHeight ? maxHeight : setHeight;
			}

			textarea
				.height(setHeight)
				.css('overflow-y', setHeight === maxHeight ? 'auto' : 'hidden')
				.trigger('vui-autoresize-change');
		}

	} );

	vui.addClassInitializer(
		'vui-autoresize',
		function( node ) {
			$( node ).vui_autoresize();
		}
	);

} )( window.vui );
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import AnimateHeight from 'react-animate-height';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import SprkIcon from '../../icons/react/SprkIcon';
import SprkLink from '../../../base/links/react/SprkLink';

class SprkAccordionItem extends Component {
  constructor(props) {
    super(props);
    const { isDefaultOpen } = this.props;
    this.state = {
      isOpen: isDefaultOpen || false,
      height: isDefaultOpen ? 'auto' : 0,
    };
    this.toggle = this.toggle.bind(this);
  }

  toggle(e) {
    const { onToggle } = this.props;
    e.preventDefault();
    this.setState(prevState => ({
      isOpen: !prevState.isOpen,
      height: !prevState.isOpen ? 'auto' : 0,
    }));
    if (onToggle) onToggle(e);
  }

  render() {
    const {
      analyticsString,
      idString,
      children,
      heading,
      headingAddClasses,
      additionalClasses,
      contentAddClasses,
      iconAddClasses,
      isDefaultOpen,
      id,
      ...other
    } = this.props;
    const { isOpen, height } = this.state;

    const iconClasses = classnames(
      'sprk-c-Icon--l sprk-c-Icon--toggle sprk-c-Accordion__icon',
      { 'sprk-c-Icon--open': isOpen },
      iconAddClasses,
    );

    const itemClassNames = classnames(
      'sprk-c-Accordion__item',
      { 'sprk-c-Accordion__item--open': isOpen },
      additionalClasses,
    );

    const headingClassNames = classnames(
      'sprk-c-Accordion__heading',
      'sprk-b-TypeDisplaySeven',
      headingAddClasses,
    );

    return (

        <SprkLink
          variant="unstyled"
          aria-controls={id}
          additionalClasses="sprk-c-Accordion__summary"
          data-analytics={analyticsString}
          onClick={this.toggle}
          aria-expanded={isOpen ? 'true' : 'false'}
        >

{heading}

          <SprkIcon
            iconName="chevron-up-circle-two-color"
            additionalClasses={iconClasses}
          />
        </SprkLink>

        <AnimateHeight duration={300} height={height}>

            {children}

        </AnimateHeight>

    );
  }
}

SprkAccordionItem.defaultProps = {
  isDefaultOpen: false,
};

SprkAccordionItem.propTypes = {
  // Content for the item
  children: PropTypes.node,
  // Value for the data-analytics attribute on the accordion trigger
  analyticsString: PropTypes.string,
  // The item heading
  heading: PropTypes.string.isRequired,
  // Additional classes for the heading
  headingAddClasses: PropTypes.string,
  // Additional classes for the item
  additionalClasses: PropTypes.string,
  // The data-id value for the accordion item
  idString: PropTypes.string,
  // Used to specify whether the item should be open by default
  isDefaultOpen: PropTypes.bool,
  // Additional classes for the toggle icon
  iconAddClasses: PropTypes.string,
  // Additional classes for the toggle content
  contentAddClasses: PropTypes.string,
};

export default SprkAccordionItem;
<commit_msg>Update comments for SprkAccordionItem<commit_after>import React, { Component } from 'react';
import AnimateHeight from 'react-animate-height';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import SprkIcon from '../../icons/react/SprkIcon';
import SprkLink from '../../../base/links/react/SprkLink';

class SprkAccordionItem extends Component {
  constructor(props) {
    super(props);
    const { isDefaultOpen } = this.props;
    this.state = {
      isOpen: isDefaultOpen || false,
      height: isDefaultOpen ? 'auto' : 0,
    };
    this.toggle = this.toggle.bind(this);
  }

  toggle(e) {
    const { onToggle } = this.props;
    e.preventDefault();
    this.setState(prevState => ({
      isOpen: !prevState.isOpen,
      height: !prevState.isOpen ? 'auto' : 0,
    }));
    if (onToggle) onToggle(e);
  }

  render() {
    const {
      analyticsString,
      idString,
      children,
      heading,
      headingAddClasses,
      additionalClasses,
      contentAddClasses,
      iconAddClasses,
      isDefaultOpen,
      id,
      ...other
    } = this.props;
    const { isOpen, height } = this.state;

    const iconClasses = classnames(
      'sprk-c-Icon--l sprk-c-Icon--toggle sprk-c-Accordion__icon',
      { 'sprk-c-Icon--open': isOpen },
      iconAddClasses,
    );

    const itemClassNames = classnames(
      'sprk-c-Accordion__item',
      { 'sprk-c-Accordion__item--open': isOpen },
      additionalClasses,
    );

    const headingClassNames = classnames(
      'sprk-c-Accordion__heading',
      'sprk-b-TypeDisplaySeven',
      headingAddClasses,
    );

    return (

        <SprkLink
          variant="unstyled"
          aria-controls={id}
          additionalClasses="sprk-c-Accordion__summary"
          data-analytics={analyticsString}
          onClick={this.toggle}
          aria-expanded={isOpen ? 'true' : 'false'}
        >

{heading}

          <SprkIcon
            iconName="chevron-up-circle-two-color"
            additionalClasses={iconClasses}
          />
        </SprkLink>

        <AnimateHeight duration={300} height={height}>

            {children}

        </AnimateHeight>

    );
  }
}

SprkAccordionItem.defaultProps = {
  isDefaultOpen: false,
};

SprkAccordionItem.propTypes = {
  /** Content for the item */
  children: PropTypes.node,
  /** Value for the data-analytics attribute on the accordion trigger */
  analyticsString: PropTypes.string,
  /** The item heading */
  heading: PropTypes.string.isRequired,
  /** Additional classes for the heading */
  headingAddClasses: PropTypes.string,
  /** Additional classes for the item */
  additionalClasses: PropTypes.string,
  /** The data-id value for the accordion item */
  idString: PropTypes.string,
  /** Used to specify whether the item should be open by default */
  isDefaultOpen: PropTypes.bool,
  /** Additional classes for the toggle icon */
  iconAddClasses: PropTypes.string,
  /** Additional classes for the toggle content */
  contentAddClasses: PropTypes.string,
};

export default SprkAccordionItem;
<|endoftext|>


<commit_before>
/*
 |--------------------------------------------------------------------------
 | Browser-sync config file
 |--------------------------------------------------------------------------
 |
 | For up-to-date information about the options:
 |   http://www.browsersync.io/docs/options/
 |
 | There are more options than you see here, these are just the ones that are
 | set internally. See the website for more info.
 |
 |
 */
module.exports = {
//    "files": ["./assets/css/*.css", "./**.*.html", "./assets/js/**/*.js"],
    "files": ["dist/*.html", "dist/assets/css/*.css", "dist/assets/js/*.js"],
    "server": 'dist',
    "proxy": false,
    "port": 3000,
    "ghostMode": {
        "clicks": true,
        "scroll": true,
        "location": false,
        "forms": {
            "submit": true,
            "inputs": true,
            "toggles": true
        }
    },
    "logLevel": "info",
    "logPrefix": "BS",
    "logConnections": false,
    "logFileChanges": true,
    "logSnippet": true,
    "open": "local",
    "browser": "default",
    "xip": false,
    "hostnameSuffix": false,
    "notify": true,
    "scrollProportionally": true,
    "scrollThrottle": 0,
    "reloadDelay": 0,
    "injectChanges": true,
    "startPath": null,
    "minify": true,
    "host": null,
    "codeSync": true,
    "timestamps": true,
    "socket": {
        "path": "/browser-sync/socket.io",
        "clientPath": "/browser-sync",
        "namespace": "/browser-sync"
    },
    "debugInfo": true
};<commit_msg>cleanup<commit_after>
/*
 |--------------------------------------------------------------------------
 | Browser-sync config file
 |--------------------------------------------------------------------------
 |
 | For up-to-date information about the options:
 |   http://www.browsersync.io/docs/options/
 |
 | There are more options than you see here, these are just the ones that are
 | set internally. See the website for more info.
 |
 |
 */
module.exports = {
    "files": ["dist/*.html", "dist/assets/css/*.css", "dist/assets/js/*.js"],
    "server": 'dist',
    "proxy": false,
    "port": 3000,
    "ghostMode": {
        "clicks": true,
        "scroll": true,
        "location": false,
        "forms": {
            "submit": true,
            "inputs": true,
            "toggles": true
        }
    },
    "logLevel": "info",
    "logPrefix": "BS",
    "logConnections": false,
    "logFileChanges": true,
    "logSnippet": true,
    "open": "local",
    "browser": "default",
    "xip": false,
    "hostnameSuffix": false,
    "notify": true,
    "scrollProportionally": true,
    "scrollThrottle": 0,
    "reloadDelay": 0,
    "injectChanges": true,
    "startPath": null,
    "minify": true,
    "host": null,
    "codeSync": true,
    "timestamps": true,
    "socket": {
        "path": "/browser-sync/socket.io",
        "clientPath": "/browser-sync",
        "namespace": "/browser-sync"
    },
    "debugInfo": true
};<|endoftext|>


<commit_before>'use strict';

var app = require('connect')();
var http = require('http');
var swaggerTools = require('swagger-tools');
var jsyaml = require('js-yaml');
var fs = require('fs');
var serverPort = 8080;

// swaggerRouter configuration
var options = {
  swaggerUi: '/swagger.json',
  controllers: './controllers',
  useStubs: process.env.NODE_ENV === 'development' ? true : false // Conditionally turn on stubs (mock mode)
};

// The Swagger document (require it, build it programmatically, fetch it from a URL, ...)
var spec = fs.readFileSync('./api/swagger.yaml', 'utf8');
var swaggerDoc = jsyaml.safeLoad(spec);

// Initialize the Swagger middleware
swaggerTools.initializeMiddleware(swaggerDoc, function (middleware) {
  // Interpret Swagger resources and attach metadata to request - must be first in swagger-tools middleware chain
  app.use(middleware.swaggerMetadata());

  // Validate Swagger requests
  app.use(middleware.swaggerValidator());

  // Route validated requests to appropriate controller
  app.use(middleware.swaggerRouter(options));

  // Serve the Swagger documents and Swagger UI
  app.use(middleware.swaggerUi());

  // Start the server
  http.createServer(app).listen(serverPort, function () {
    console.log('Your server is listening on port %d (http://localhost:%d)', serverPort, serverPort);
    console.log('Swagger-ui is available on http://localhost:%d/docs', serverPort);
  });
});
<commit_msg>Use environment variable port<commit_after>'use strict';

var app = require('connect')();
var http = require('http');
var swaggerTools = require('swagger-tools');
var jsyaml = require('js-yaml');
var fs = require('fs');
var serverPort = process.env.PORT || 8080; // use port 8080 unless there exists a preconfigured port

// swaggerRouter configuration
var options = {
  swaggerUi: '/swagger.json',
  controllers: './controllers',
  useStubs: process.env.NODE_ENV === 'development' ? true : false // Conditionally turn on stubs (mock mode)
};

// The Swagger document (require it, build it programmatically, fetch it from a URL, ...)
var spec = fs.readFileSync('./api/swagger.yaml', 'utf8');
var swaggerDoc = jsyaml.safeLoad(spec);

// Initialize the Swagger middleware
swaggerTools.initializeMiddleware(swaggerDoc, function (middleware) {
  // Interpret Swagger resources and attach metadata to request - must be first in swagger-tools middleware chain
  app.use(middleware.swaggerMetadata());

  // Validate Swagger requests
  app.use(middleware.swaggerValidator());

  // Route validated requests to appropriate controller
  app.use(middleware.swaggerRouter(options));

  // Serve the Swagger documents and Swagger UI
  app.use(middleware.swaggerUi());

  // Start the server
  http.createServer(app).listen(serverPort, function () {
    console.log('Your server is listening on port %d (http://localhost:%d)', serverPort, serverPort);
    console.log('Swagger-ui is available on http://localhost:%d/docs', serverPort);
  });
});
<|endoftext|>


<commit_before>module.exports = {
  title: 'Gerbil Scheme',
  description: '',
  themeConfig: {
    nav: [
      { text: 'Home', link: '/' },
      { text: 'Guide', link: '/guide/' },
      { text: 'Tutorials', link: '/tutorials/' },
      { text: 'Reference', link: '/reference/' },
    ],
    sidebarDepth: 2,
    sidebar: {
      '/guide/': [
        {
          collapsable: false,
          title: 'Guide',
          children: ['', 'intro', 'getting-started', 'emacs', 'shell', 'env-vars', 'package-manager', 'ffi', 'build', 'profiler', 'bootstrap', 'nix', 'r7rs', 'srfi']
        }
      ],
      '/tutorials/': [
          {
            collapsable: false,
            title: 'Tutorials',
            children: ['', 'languages', 'kvstore', 'proxy', 'httpd']
          }
      ],
      '/reference/': [
        {
          collapsable: false,
          title: 'Gerbil Reference',
          children:  ['', 'core-prelude', 'core-builtin', 'core-expander', 'stdlib', 'sugar', 'errors', 'getopt', 'format', 'logger', 'sort', 'regexp', 'generic', 'ref', 'iterators', 'coroutine', 'events', 'actor', 'requests', 'httpd', 'web', 'db', 'kvstore', 'sockets', 'net', 'protobuf', 'os', 'crypto', 'text', 'xml', 'parser', 'misc', 'lazy', 'amb', 'stxparam', 'stxutil', 'foreign', 'srfi', 'test', 'debug', 'make']
        }
      ]
    },
    // Assumes GitHub. Can also be a full GitLab url.
    repo: 'vyzo/gerbil',
    // Customising the header label
    // Defaults to "GitHub"/"GitLab"/"Bitbucket" depending on `themeConfig.repo`
    repoLabel: 'Contribute!',

    // Optional options for generating "Edit this page" link

    // if your docs are in a different repo from your main project:
    docsRepo: 'vyzo/gerbil',
    // if your docs are not at the root of the repo:
    docsDir: 'doc',
    // if your docs are in a specific branch (defaults to 'master'):
    docsBranch: 'master',
    // defaults to false, set to true to enable
    editLinks: true,
    // custom text for edit link. Defaults to "Edit this page"
    editLinkText: 'Help us improve this page!',
  },
  module: {
    rules: [
      {
        test: /\.svg$/,
        loader: 'vue-svg-loader',
      },
    ],
  },
  current_version: 'v0.12'
}
<commit_msg>doc: add gitter link to navbar<commit_after>module.exports = {
  title: 'Gerbil Scheme',
  description: '',
  themeConfig: {
    nav: [
      { text: 'Home', link: '/' },
      { text: 'Guide', link: '/guide/' },
      { text: 'Tutorials', link: '/tutorials/' },
      { text: 'Reference', link: '/reference/' },
      { text: 'Gitter', link: 'https://gitter.im/gerbil-scheme/community' }
    ],
    sidebarDepth: 2,
    sidebar: {
      '/guide/': [
        {
          collapsable: false,
          title: 'Guide',
          children: ['', 'intro', 'getting-started', 'emacs', 'shell', 'env-vars', 'package-manager', 'ffi', 'build', 'profiler', 'bootstrap', 'nix', 'r7rs', 'srfi']
        }
      ],
      '/tutorials/': [
          {
            collapsable: false,
            title: 'Tutorials',
            children: ['', 'languages', 'kvstore', 'proxy', 'httpd']
          }
      ],
      '/reference/': [
        {
          collapsable: false,
          title: 'Gerbil Reference',
          children:  ['', 'core-prelude', 'core-builtin', 'core-expander', 'stdlib', 'sugar', 'errors', 'getopt', 'format', 'logger', 'sort', 'regexp', 'generic', 'ref', 'iterators', 'coroutine', 'events', 'actor', 'requests', 'httpd', 'web', 'db', 'kvstore', 'sockets', 'net', 'protobuf', 'os', 'crypto', 'text', 'xml', 'parser', 'misc', 'lazy', 'amb', 'stxparam', 'stxutil', 'foreign', 'srfi', 'test', 'debug', 'make']
        }
      ]
    },
    // Assumes GitHub. Can also be a full GitLab url.
    repo: 'vyzo/gerbil',
    // Customising the header label
    // Defaults to "GitHub"/"GitLab"/"Bitbucket" depending on `themeConfig.repo`
    repoLabel: 'Contribute!',

    // Optional options for generating "Edit this page" link

    // if your docs are in a different repo from your main project:
    docsRepo: 'vyzo/gerbil',
    // if your docs are not at the root of the repo:
    docsDir: 'doc',
    // if your docs are in a specific branch (defaults to 'master'):
    docsBranch: 'master',
    // defaults to false, set to true to enable
    editLinks: true,
    // custom text for edit link. Defaults to "Edit this page"
    editLinkText: 'Help us improve this page!',
  },
  module: {
    rules: [
      {
        test: /\.svg$/,
        loader: 'vue-svg-loader',
      },
    ],
  },
  current_version: 'v0.12'
}
<|endoftext|>


<commit_before>const path = require("path");
const ROOT = "../../";
const webpack = require('webpack');

const { AotPlugin } = require('@ngtools/webpack');

const useAOT = false;

let tsLoader = {
        test: /\.ts/,
        loaders: ['awesome-typescript-loader', 'angular2-template-loader'],
        exclude: /node_modules/
};

let plugins = [];
if (useAOT) {
        const aot = new AotPlugin({
                tsConfigPath: path.normalize(ROOT + "./tsconfig.json")
                //entryModule:  "../../src/public/app/browser-app.module#BrowserAppModule"
        });
        plugins.push(aot);
        tsLoader = {
                test: /\.ts$/,
                loader: '@ngtools/webpack',
        };
}

module.exports = {
        entry: {
        app: path.normalize(ROOT + "./src/public/app/main.browser")
        },
        output: {
                path: __dirname,
                filename: path.normalize(ROOT +"./.build/public/dist/[name].js")
        },
                resolve: {
                extensions: [ '.ts', '.js']
        },
        module: {
                loaders: [
                        tsLoader,
                        {
                                test: /\.(html|css)$/,
                                loader: 'raw-loader'
                        },
                        {
                                test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
                                loader: 'null'
                        },
                ]
        },
        plugins: plugins
};<commit_msg>migration to Angular 4<commit_after>const config = require('../config/config.json');
const path = require("path");
const ROOT = "../../";
const webpack = require('webpack');
const {AotPlugin} = require('@ngtools/webpack');

let useAOT = false;

if (!config.development) {
        useAOT = true;
}

let tsLoader = {
        test: /\.ts/,
        loaders: ['awesome-typescript-loader', 'angular2-template-loader'],
        exclude: /node_modules/
};

let plugins = [];
if (useAOT) {
        const aot = new AotPlugin({
                tsConfigPath: path.normalize(ROOT + "./tsconfig.json")
                //entryModule:  "../../src/public/app/browser-app.module#BrowserAppModule"
        });
        plugins.push(aot);
        tsLoader = {
                test: /\.ts$/,
                loader: '@ngtools/webpack',
        };
}

module.exports = {
        entry: {
        app: path.normalize(ROOT + "./src/public/app/main.browser")
        },
        output: {
                path: __dirname,
                filename: path.normalize(ROOT +"./.build/public/dist/[name].js")
        },
                resolve: {
                extensions: [ '.ts', '.js']
        },
        module: {
                loaders: [
                        tsLoader,
                        {
                                test: /\.(html|css)$/,
                                loader: 'raw-loader'
                        },
                        {
                                test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
                                loader: 'null'
                        },
                ]
        },
        plugins: plugins
};<|endoftext|>


<commit_before>/*
 Tab Bar AutoScroll Library for Vertical and Horizontal Tab Bar

 Usage:
   var scrolled = window['piro.sakura.ne.jp']
                        .autoScroll
                        .processAutoScroll(mouseMoveOrDragOverEvent);

 lisence: The MIT License, Copyright (c) 2009 SHIMODA "Piro" Hiroshi
   http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/license.txt
 original:
   http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/autoScroll.js
*/
(function() {
	const currentRevision = 1;

	if (!('piro.sakura.ne.jp' in window)) window['piro.sakura.ne.jp'] = {};

	var loadedRevision = 'autoScroll' in window['piro.sakura.ne.jp'] ?
			window['piro.sakura.ne.jp'].autoScroll.revision :
			0 ;
	if (loadedRevision && loadedRevision > currentRevision) {
		return;
	}

	var Cc = Components.classes;
	var Ci = Components.interfaces;

	window['piro.sakura.ne.jp'].autoScroll = {
		revision : currentRevision,

		processAutoScroll : function(aEvent)
		{
			var target = aEvent.originalTarget;
			var b = target.ownerDocument.evaluate(
					'ancestor-or-self::*[local-name()="tabbrowser"]',
					target,
					null,
					XPathResult.FIRST_ORDERED_NODE_TYPE,
					null
				).singleNodeValue;
			if (!b) return false;

			var tabs = b.mTabContainer;
			if (tabs.getAttribute('overflow') != 'true')
				return false;

			var box        = this.getScrollBox(b);
			var boxObject  = this.getScrollBoxObject(b);
			var innerBoxObject = (box.localName == 'arrowscrollbox' ? box._scrollbox : box ).boxObject;

			var orientBox = box || tabs;
			var isVertical = (orientBox.getAttribute('orient') || window.getComputedStyle(orientBox, '').getPropertyValue('-moz-box-orient')) == 'vertical';

			var maxX = {}, maxY = {}, curX = {}, curY = {};
			boxObject.getScrolledSize(maxX, maxY);
			boxObject.getPosition(curX, curY);

			var pixels;
			if (isVertical) {
				pixels = tabs.childNodes[0].boxObject.height * 0.5;
				if (aEvent.screenY < boxObject.screenY + this.getUpButtonHeight(b)) {
					if (curY.value == 0) return false;
					pixels *= -1;
				}
				else if (aEvent.screenY > boxObject.screenY + boxObject.height - this.getDownButtonHeight(b)) {
					if (innerBoxObject.height + curY.value == maxY.value) return false;
				}
				else {
					return false;
				}
			}
			else {
				pixels = box.scrollIncrement;
				var ltr = window.getComputedStyle(tabs, null).direction == 'ltr';
				if (aEvent.screenX < boxObject.screenX + this.getUpButtonWidth(b)) {
					if (curX.value == 0) return false;
					pixels *= -1;
				}
				else if (aEvent.screenX > boxObject.screenX + boxObject.width - this.getDownButtonWidth(b)) {
					if (innerBoxObject.width + curX.value == maxX.value) return false;
					return false;
				}
				else {
					return false;
				}
				pixels = (ltr ? 1 : -1) * pixels;
			}

			if ('scrollByPixels' in box) {
				box.scrollByPixels(pixels);
			}
			else { // Tab Mix Plus?
				if (isVertical)
					boxObject.scrollBy(0, pixels);
				else
					boxObject.scrollBy(pixels, 0);
			}
			return true;
		},

		getScrollBox : function(aTabBrowser)
		{
			return document.getAnonymousElementByAttribute(aTabBrowser.mTabContainer, 'class', 'tabs-frame') || // Tab Mix Plus
					aTabBrowser.mTabContainer.mTabstrip;
		},

		getScrollBoxObject : function(aTabBrowser)
		{
			var box = this.getScrollBox(aTabBrowser);
			return box.scrollBoxObject ||
					box.boxObject.QueryInterface(Ci.nsIScrollBoxObject); // Tab Mix Plus
		},

		getUpButton : function(aTabBrowser)
		{
			var box = this.getScrollBox(aTabBrowser);
			return box._scrollButtonUp ||
				document.getAnonymousElementByAttribute(box, 'class', 'scrollbutton-up') ||
				document.getAnonymousElementByAttribute(box.previousSibling, 'class', 'scrollbutton-up'); // Tab Mix Plus
		},
		getDownButton : function(aTabBrowser)
		{
			var box = this.getScrollBox(aTabBrowser);
			return box._scrollButtonDown ||
				document.getAnonymousElementByAttribute(box, 'class', 'scrollbutton-down') ||
				document.getAnonymousElementByAttribute(box.nextSibling, 'class', 'scrollbutton-up'); // Tab Mix Plus
		},

		autoScrollArea : 20,

		getUpButtonHeight : function(aTabBrowser)
		{
			var button = this.getUpButton(aTabBrowser);
			return (button ? button.boxObject.height : 0 ) || this.autoScrollArea;
		},
		getUpButtonWidth : function(aTabBrowser)
		{
			var button = this.getUpButton(aTabBrowser);
			return (button ? button.boxObject.width : 0 ) || this.autoScrollArea;
		},

		getDownButtonHeight : function(aTabBrowser)
		{
			var button = this.getDownButton(aTabBrowser);
			return (button ? button.boxObject.height : 0 ) || this.autoScrollArea;
		},
		getDownButtonWidth : function(aTabBrowser)
		{
			var button = this.getDownButton(aTabBrowser);
			return (button ? button.boxObject.width : 0 ) || this.autoScrollArea;
		}

	};
})();
<commit_msg>Tab Mix Plusの複数行タブバーとの連携を改善（複数行タブバーでは縦方向にスクロールするように）<commit_after>/*
 Tab Bar AutoScroll Library for Vertical and Horizontal Tab Bar

 Usage:
   var scrolled = window['piro.sakura.ne.jp']
                        .autoScroll
                        .processAutoScroll(mouseMoveOrDragOverEvent);

 lisence: The MIT License, Copyright (c) 2009 SHIMODA "Piro" Hiroshi
   http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/license.txt
 original:
   http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/autoScroll.js
*/
(function() {
	const currentRevision = 2;

	if (!('piro.sakura.ne.jp' in window)) window['piro.sakura.ne.jp'] = {};

	var loadedRevision = 'autoScroll' in window['piro.sakura.ne.jp'] ?
			window['piro.sakura.ne.jp'].autoScroll.revision :
			0 ;
	if (loadedRevision && loadedRevision > currentRevision) {
		return;
	}

	var Cc = Components.classes;
	var Ci = Components.interfaces;

	window['piro.sakura.ne.jp'].autoScroll = {
		revision : currentRevision,

		processAutoScroll : function(aEvent)
		{
			var target = aEvent.originalTarget;
			var b = target.ownerDocument.evaluate(
					'ancestor-or-self::*[local-name()="tabbrowser"]',
					target,
					null,
					XPathResult.FIRST_ORDERED_NODE_TYPE,
					null
				).singleNodeValue;
			if (!b) return false;

			var tabs = b.mTabContainer;
			if (tabs.getAttribute('overflow') != 'true')
				return false;

			var box        = this.getScrollBox(b);
			var boxObject  = this.getScrollBoxObject(b);
			var innerBoxObject = (box.localName == 'arrowscrollbox' ? box._scrollbox : box ).boxObject;

			var orientBox = box || tabs;
			var isMultirow = tabs.getAttribute('flowing') == 'multibar'; // Tab Mix Plus
			var isVertical = (
					isMultirow ||
					((orientBox.getAttribute('orient') || window.getComputedStyle(orientBox, '').getPropertyValue('-moz-box-orient')) == 'vertical')
				);

			var maxX = {}, maxY = {}, curX = {}, curY = {};
			boxObject.getScrolledSize(maxX, maxY);
			boxObject.getPosition(curX, curY);

			var pixels;
			if (isVertical) {
				pixels = tabs.childNodes[0].boxObject.height * 0.5;
				if (isMultirow) pixels *= 0.5;
				if (aEvent.screenY < boxObject.screenY + this.getUpButtonHeight(b)) {
					if (curY.value == 0) return false;
					pixels *= -1;
				}
				else if (aEvent.screenY > boxObject.screenY + boxObject.height - this.getDownButtonHeight(b)) {
					if (innerBoxObject.height + curY.value == maxY.value) return false;
				}
				else {
					return false;
				}
			}
			else {
				pixels = box.scrollIncrement;
				var ltr = window.getComputedStyle(tabs, null).direction == 'ltr';
				if (aEvent.screenX < boxObject.screenX + this.getUpButtonWidth(b)) {
					if (curX.value == 0) return false;
					pixels *= -1;
				}
				else if (aEvent.screenX > boxObject.screenX + boxObject.width - this.getDownButtonWidth(b)) {
					if (innerBoxObject.width + curX.value == maxX.value) return false;
					return false;
				}
				else {
					return false;
				}
				pixels = (ltr ? 1 : -1) * pixels;
			}

			if ('scrollByPixels' in box) {
				box.scrollByPixels(pixels);
			}
			else { // Tab Mix Plus?
				if (isVertical)
					boxObject.scrollBy(0, pixels);
				else
					boxObject.scrollBy(pixels, 0);
			}
			return true;
		},

		getScrollBox : function(aTabBrowser)
		{
			return document.getAnonymousElementByAttribute(aTabBrowser.mTabContainer, 'class', 'tabs-frame') || // Tab Mix Plus
					aTabBrowser.mTabContainer.mTabstrip;
		},

		getScrollBoxObject : function(aTabBrowser)
		{
			var box = this.getScrollBox(aTabBrowser);
			return (box.scrollBoxObject || box.boxObject)
					.QueryInterface(Ci.nsIScrollBoxObject); // Tab Mix Plus
		},

		getUpButton : function(aTabBrowser)
		{
			var box = this.getScrollBox(aTabBrowser);
			return box._scrollButtonUp ||
				document.getAnonymousElementByAttribute(box, 'class', 'scrollbutton-up') ||
				document.getAnonymousElementByAttribute(box.previousSibling, 'class', 'scrollbutton-up'); // Tab Mix Plus
		},
		getDownButton : function(aTabBrowser)
		{
			var box = this.getScrollBox(aTabBrowser);
			return box._scrollButtonDown ||
				document.getAnonymousElementByAttribute(box, 'class', 'scrollbutton-down') ||
				document.getAnonymousElementByAttribute(box.nextSibling, 'class', 'scrollbutton-up'); // Tab Mix Plus
		},

		autoScrollArea : 20,

		getUpButtonHeight : function(aTabBrowser)
		{
			var button = this.getUpButton(aTabBrowser);
			return (button ? button.boxObject.height : 0 ) || this.autoScrollArea;
		},
		getUpButtonWidth : function(aTabBrowser)
		{
			var button = this.getUpButton(aTabBrowser);
			return (button ? button.boxObject.width : 0 ) || this.autoScrollArea;
		},

		getDownButtonHeight : function(aTabBrowser)
		{
			var button = this.getDownButton(aTabBrowser);
			return (button ? button.boxObject.height : 0 ) || this.autoScrollArea;
		},
		getDownButtonWidth : function(aTabBrowser)
		{
			var button = this.getDownButton(aTabBrowser);
			return (button ? button.boxObject.width : 0 ) || this.autoScrollArea;
		}

	};
})();
<|endoftext|>


<commit_before><commit_msg>Attached amtterm to stdin and stdout<commit_after><|endoftext|>


<commit_before>'use strict';

//var Menu = React.createClass({
//    displayName: 'Menu',

//    render: function render() {
//        var menus = [{ name: 'Home', link: '#home' }, { name: 'Portfolio', link: '#portfolio' }, { name: 'Article', link: '#article' }, { name: 'About', link: '#about' }];
//        return React.createElement(
//            'ul',
//            { className: 'menu' },
//            menus.map(function (item) {
//                return React.createElement(
//                    'li',
//                    null,
//                    React.createElement(
//                        'a',
//                        { href: item.link },
//                        item.name
//                    )
//                );
//            })
//        );
//    }
//});

var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
var _ReactRouter = ReactRouter;
var Router = _ReactRouter.Router;
var Link = _ReactRouter.Link;
var Route = _ReactRouter.Route;
var IndexRoute = _ReactRouter.IndexRoute;

var App = React.createClass({
    displayName: 'App',

    render: function render() {
        var pathname = this.props.location.pathname;

        return React.createElement(
            'div',
            { className: 'container' },
            React.createElement(
                'div',
                { className: 'header' },
                React.createElement(
                    'div',
                    { className: 'row' },
                    React.createElement(
                        'div',
                        { className: 'four columns' },
                        //React.createElement(
                           // Link,
                         //   { to: 'home' },
                       //     React.createElement('div', { className: 'logo' })
                     //   )
                   // )
                    //React.createElement(
                      //  'div',
                        //{ className: 'eight columns' },
                        //React.createElement(Menu, null)
                    //)
                )
            ),
            React.createElement(
                'div',
                { className: 'content' },
                React.createElement(
                    ReactCSSTransitionGroup,
                    { component: 'div', transitionName: 'example', transitionEnterTimeout: 500, transitionLeaveTimeout: 500 },
                    React.cloneElement(this.props.children || React.createElement('div', null), { key: pathname })
                )
            )
        );
    }
});

ReactDOM.render(React.createElement(
    Router,
    null,
    React.createElement(
        Route,
        { path: '/', component: App },
        React.createElement(IndexRoute, { component: Home }),
        React.createElement(Route, { path: 'home', component: Home }),
        React.createElement(Route, { path: 'portfolio', component: Portfolio }),
        React.createElement(Route, { path: 'article', component: Article }),
        React.createElement(Route, { path: 'about', component: About }),
        React.createElement(Route, { path: 'post/:slug', component: Post })
    )
), document.getElementById('root'));
<commit_msg>Update app.js<commit_after>'use strict';

//var Menu = React.createClass({
//    displayName: 'Menu',

//    render: function render() {
//        var menus = [{ name: 'Home', link: '#home' }, { name: 'Portfolio', link: '#portfolio' }, { name: 'Article', link: '#article' }, { name: 'About', link: '#about' }];
//        return React.createElement(
//            'ul',
//            { className: 'menu' },
//            menus.map(function (item) {
//                return React.createElement(
//                    'li',
//                    null,
//                    React.createElement(
//                        'a',
//                        { href: item.link },
//                        item.name
//                    )
//                );
//            })
//        );
//    }
//});

var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
var _ReactRouter = ReactRouter;
var Router = _ReactRouter.Router;
var Link = _ReactRouter.Link;
var Route = _ReactRouter.Route;
var IndexRoute = _ReactRouter.IndexRoute;

var App = React.createClass({
    displayName: 'App',

    render: function render() {
        var pathname = this.props.location.pathname;

        return React.createElement(
            'div',
            { className: 'container' },
            React.createElement(
                'div',
                { className: 'header' },
               // React.createElement(
                //    'div',
                //    { className: 'row' },
              //      React.createElement(
              //          'div',
              //          { className: 'four columns' },
                        //React.createElement(
                           // Link,
                         //   { to: 'home' },
                       //     React.createElement('div', { className: 'logo' })
                     //   )
                   // )
                    //React.createElement(
                      //  'div',
                        //{ className: 'eight columns' },
                        //React.createElement(Menu, null)
                    //)
                )
            ),
            React.createElement(
                'div',
                { className: 'content' },
                React.createElement(
                    ReactCSSTransitionGroup,
                    { component: 'div', transitionName: 'example', transitionEnterTimeout: 500, transitionLeaveTimeout: 500 },
                    React.cloneElement(this.props.children || React.createElement('div', null), { key: pathname })
                )
            )
        );
    }
});

ReactDOM.render(React.createElement(
    Router,
    null,
    React.createElement(
        Route,
        { path: '/', component: App },
        React.createElement(IndexRoute, { component: Home }),
        React.createElement(Route, { path: 'home', component: Home }),
        React.createElement(Route, { path: 'portfolio', component: Portfolio }),
        React.createElement(Route, { path: 'article', component: Article }),
        React.createElement(Route, { path: 'about', component: About }),
        React.createElement(Route, { path: 'post/:slug', component: Post })
    )
), document.getElementById('root'));
<|endoftext|>


<commit_before>var _ = require('lodash');
var cache = require('../lib/cache');
var decorate = require('../presenters/package');
var fmt = require('util').format;
var P = require('bluebird');
var request = require('../lib/external-request');
var qs = require('qs');
var USER_API = process.env.USER_API || "https://user-api-example.com";
var VError = require('verror');

var Package = module.exports = function(loggedInUser) {

  if (!(this instanceof Package)) {
    return new Package(loggedInUser);
  }

  this.bearer = loggedInUser && loggedInUser.name;

  return this;
};

Package.prototype.generatePackageOpts = function generatePackageOpts(name) {
  var opts = {
    url: fmt("%s/package/%s", USER_API, name.replace("/", "%2F")),
    json: true
  };

  if (this.bearer) {
    opts.headers = {
      bearer: this.bearer
    };
  }

  return opts;
};

Package.prototype.get = function(name) {
  var opts = this.generatePackageOpts(name);

  return cache.getP(opts).then(maybeUpgradeRRPackageData).tap(assertPackageIsWellFormed).then(decorate);

};

Package.prototype.dropCache = function dropCache(name) {
  return cache.dropP(this.generatePackageOpts(name));
};

Package.prototype.update = function(name, body) {

  var url = fmt("%s/package/%s", USER_API, name.replace("/", "%2F"));
  var opts = {
    method: "POST",
    url: url,
    json: true,
    body: _.pick(body, 'private') // remove all other props
  };

  // hapi is converting the private boolean to a string
  // so... yeah.
  if (opts.body && 'private' in opts.body) {
    opts.body.private = (String(opts.body.private) === "true");
  }

  if (this.bearer) {
    opts.headers = {
      bearer: this.bearer
    };
  }

  return this.dropCache(name)
    .then(function() {
      return new P(function(resolve, reject) {
        request(opts, function(err, resp, body) {
          if (err) {
            return reject(err);
          }
          if (resp.statusCode > 399) {
            err = new Error('error updating package ' + name);
            err.statusCode = resp.statusCode;
            return reject(err);
          }
          return resolve(body);
        });
      });
    })
    .then(function(_package) {
      return _package ? decorate(_package) : {
        package: name,
        updated: true
      };
    });
};

Package.prototype.list = function(options, ttl) {
  var url = fmt("%s/package?%s", USER_API, qs.stringify(options));

  var opts = {
    url: url,
    json: true,
    ttl: ttl || 500 // seconds
  };

  return cache.getP(opts).then(function upgradeRRResponse(result) {
    if (Array.isArray(result)) {
      return {
        results: result
      };
    } else {
      return result;
    }
  });
};

Package.prototype.count = function() {
  var url = fmt("%s/package/-/count", USER_API);
  var opts = {
    url: url,
    json: true
  };

  return cache.getP(opts);
};

Package.prototype.star = function(pkg) {

  var self = this;
  var url = fmt("%s/package/%s/star", USER_API, encodeURIComponent(pkg));
  var opts = {
    url: url,
    json: true,
  };

  if (self.bearer) {
    opts.headers = {
      bearer: self.bearer
    };
  }

  return this.dropCache(pkg)
    .then(function() {
      return new P(function(resolve, reject) {

        request.put(opts, function(err, resp) {
          if (err) {
            return reject(err);
          }
          if (resp.statusCode > 399) {
            err = new Error('error starring package ' + pkg);
            err.statusCode = resp.statusCode;
            return reject(err);
          }

          return resolve(pkg + ' starred by ' + self.bearer);
        });
      });
    });
};

Package.prototype.unstar = function(pkg) {

  var self = this;
  var url = fmt("%s/package/%s/star", USER_API, encodeURIComponent(pkg));
  var opts = {
    url: url,
    json: true,
  };

  if (self.bearer) {
    opts.headers = {
      bearer: self.bearer
    };
  }

  return this.dropCache(pkg)
    .then(function() {
      return new P(function(resolve, reject) {

        request.del(opts, function(err, resp) {
          if (err) {
            return reject(err);
          }

          if (resp.statusCode > 399) {
            err = new Error('error unstarring package ' + pkg);
            err.statusCode = resp.statusCode;
            return reject(err);
          }

          return resolve(pkg + ' unstarred by ' + self.bearer);
        });
      });
    });
};

function maybeUpgradeRRPackageData(pkg) {
  if (Object.keys(pkg).length == 1) {
    pkg = pkg[Object.keys(pkg)[0]];
    // registry-relational returns several important fields
    // stored on the latest release, rather than the top level.
    if (pkg['dist-tags'] && pkg['dist-tags'].latest && pkg.versions[pkg['dist-tags'].latest]) {
      _.extend(pkg, pkg.versions[pkg['dist-tags'].latest])
    }
  }

  return pkg;
}

function assertPackageIsWellFormed(pkg) {
  if (!pkg || !pkg.name) {
    throw new VError("Package is not well formed: %j", pkg);
  }
}
<commit_msg>i like semicolons and triple equals AND THAT'S OKAY<commit_after>var _ = require('lodash');
var cache = require('../lib/cache');
var decorate = require('../presenters/package');
var fmt = require('util').format;
var P = require('bluebird');
var request = require('../lib/external-request');
var qs = require('qs');
var USER_API = process.env.USER_API || "https://user-api-example.com";
var VError = require('verror');

var Package = module.exports = function(loggedInUser) {

  if (!(this instanceof Package)) {
    return new Package(loggedInUser);
  }

  this.bearer = loggedInUser && loggedInUser.name;

  return this;
};

Package.prototype.generatePackageOpts = function generatePackageOpts(name) {
  var opts = {
    url: fmt("%s/package/%s", USER_API, name.replace("/", "%2F")),
    json: true
  };

  if (this.bearer) {
    opts.headers = {
      bearer: this.bearer
    };
  }

  return opts;
};

Package.prototype.get = function(name) {
  var opts = this.generatePackageOpts(name);

  return cache.getP(opts).then(maybeUpgradeRRPackageData).tap(assertPackageIsWellFormed).then(decorate);

};

Package.prototype.dropCache = function dropCache(name) {
  return cache.dropP(this.generatePackageOpts(name));
};

Package.prototype.update = function(name, body) {

  var url = fmt("%s/package/%s", USER_API, name.replace("/", "%2F"));
  var opts = {
    method: "POST",
    url: url,
    json: true,
    body: _.pick(body, 'private') // remove all other props
  };

  // hapi is converting the private boolean to a string
  // so... yeah.
  if (opts.body && 'private' in opts.body) {
    opts.body.private = (String(opts.body.private) === "true");
  }

  if (this.bearer) {
    opts.headers = {
      bearer: this.bearer
    };
  }

  return this.dropCache(name)
    .then(function() {
      return new P(function(resolve, reject) {
        request(opts, function(err, resp, body) {
          if (err) {
            return reject(err);
          }
          if (resp.statusCode > 399) {
            err = new Error('error updating package ' + name);
            err.statusCode = resp.statusCode;
            return reject(err);
          }
          return resolve(body);
        });
      });
    })
    .then(function(_package) {
      return _package ? decorate(_package) : {
        package: name,
        updated: true
      };
    });
};

Package.prototype.list = function(options, ttl) {
  var url = fmt("%s/package?%s", USER_API, qs.stringify(options));

  var opts = {
    url: url,
    json: true,
    ttl: ttl || 500 // seconds
  };

  return cache.getP(opts).then(function upgradeRRResponse(result) {
    if (Array.isArray(result)) {
      return {
        results: result
      };
    } else {
      return result;
    }
  });
};

Package.prototype.count = function() {
  var url = fmt("%s/package/-/count", USER_API);
  var opts = {
    url: url,
    json: true
  };

  return cache.getP(opts);
};

Package.prototype.star = function(pkg) {

  var self = this;
  var url = fmt("%s/package/%s/star", USER_API, encodeURIComponent(pkg));
  var opts = {
    url: url,
    json: true,
  };

  if (self.bearer) {
    opts.headers = {
      bearer: self.bearer
    };
  }

  return this.dropCache(pkg)
    .then(function() {
      return new P(function(resolve, reject) {

        request.put(opts, function(err, resp) {
          if (err) {
            return reject(err);
          }
          if (resp.statusCode > 399) {
            err = new Error('error starring package ' + pkg);
            err.statusCode = resp.statusCode;
            return reject(err);
          }

          return resolve(pkg + ' starred by ' + self.bearer);
        });
      });
    });
};

Package.prototype.unstar = function(pkg) {

  var self = this;
  var url = fmt("%s/package/%s/star", USER_API, encodeURIComponent(pkg));
  var opts = {
    url: url,
    json: true,
  };

  if (self.bearer) {
    opts.headers = {
      bearer: self.bearer
    };
  }

  return this.dropCache(pkg)
    .then(function() {
      return new P(function(resolve, reject) {

        request.del(opts, function(err, resp) {
          if (err) {
            return reject(err);
          }

          if (resp.statusCode > 399) {
            err = new Error('error unstarring package ' + pkg);
            err.statusCode = resp.statusCode;
            return reject(err);
          }

          return resolve(pkg + ' unstarred by ' + self.bearer);
        });
      });
    });
};

function maybeUpgradeRRPackageData(pkg) {
  if (Object.keys(pkg).length === 1) {
    pkg = pkg[Object.keys(pkg)[0]];
    // registry-relational returns several important fields
    // stored on the latest release, rather than the top level.
    if (pkg['dist-tags'] && pkg['dist-tags'].latest && pkg.versions[pkg['dist-tags'].latest]) {
      _.extend(pkg, pkg.versions[pkg['dist-tags'].latest]);
    }
  }

  return pkg;
}

function assertPackageIsWellFormed(pkg) {
  if (!pkg || !pkg.name) {
    throw new VError("Package is not well formed: %j", pkg);
  }
}
<|endoftext|>


<commit_before>
/**
 * Cornerstone Framework Build Job
 */
var fs = require( 'fs' );
var zlib = require( 'zlib' );
var wrench = require( 'wrench' );
var glob = require( 'glob' );
var colorize = require( 'colorize' );
var jsp = require( 'uglify-js' ).parser;
var pro = require( 'uglify-js' ).uglify;
var less = require( 'less' );
var Step = require( 'step' );

const ENCODING = 'utf-8';

var log = exports.log = function( msg ) {
	msg ? colorize.console.log( msg ) : console.log();
};

var action = exports.action = function( action, file ) {

	// 줄맞춤을 위해 공백을 추가한다.
	const MAX_ACTION_LENGTH = 13;
	var actionLength = action.length;
	if ( actionLength < MAX_ACTION_LENGTH )
		for ( var i = 0; i < MAX_ACTION_LENGTH - actionLength; i++ ) action += ' ';

	colorize.console.log( '    - #cyan[(' + action + ')]: ' + file );
};

exports.mkdir = function( path ) {
	wrench.mkdirSyncRecursive( path );
	action( 'Created', path );
};

exports.copy = function( src, dest ) {
	wrench.copyDirSyncRecursive( src, dest );
	action( 'Copied', src + ' => ' + dest );
};

exports.concat = function() {

	var first = arguments[ 0 ];
	var last = arguments[ arguments.length - 1 ];
	var lastContent;

	try {
		lastContent = fs.readFileSync( last );
	}
	catch ( e ) {}

	action( 'Concatenating', first );
	fs.writeFileSync( last, fs.readFileSync( first ) );

	for ( var i = 1; i < arguments.length - 1; i++ ) {
		action( 'Concatenating', arguments[ i ] );
		fs.appendFileSync( last, fs.readFileSync( arguments[ i ] ) );
	}

	action( 'Concatenating', last );
	fs.appendFileSync( last, lastContent );

	action( 'Concatenated', last );
};

exports.less = function( src, dest, cb ) {

	action( 'Compiling', src + ' => ' + dest );

	var parser = new( less.Parser )( {
		paths: [ src.substring( 0, src.lastIndexOf( '/' ) ) ]
	} );

	parser.parse( fs.readFileSync( src, ENCODING ), function( err, tree ) {
		if ( err ) {
			console.log( err );
			cb( err );
			return;
		}

		fs.writeFileSync( dest, tree.toCSS(), ENCODING );
		action( 'Compiled', src + ' => ' + dest );

		cb();
	} );
};

exports.files = function( base, pattern ) {

	return {

		// pattern에 맞는 파일명 목록 (base 부분을 제외한다.)
		_files: glob( base + pattern, { sync: true } ).map( function( file ) {
			return file.substring( 0, base.length ) === base ? file.substring( base.length ) : file;
		} ),

		// 삭제
		delete: function() {
			this._files.forEach( function( file, index, array ) {
				action( 'Deleting', base + file );
				fs.lstatSync( base + file ).isDirectory() ? wrench.rmdirSyncRecursive( base + file ) : fs.unlinkSync( base + file );
				action( 'Deleted', base + file );
			} );
		},

		// 최소화
		minify: function( dest ) {
			this._files.forEach( function( file, index, array ) {
				action( 'Minifying', base + file );
				var content = fs.readFileSync( base + file, ENCODING );
				var ast = jsp.parse( content );
				ast = pro.ast_mangle( ast );
				ast = pro.ast_squeeze( ast );
				fs.writeFileSync( dest + file, pro.gen_code( ast ), ENCODING );
				action( 'Minified', dest + file );
			} );
		},

		// gzip 압축
		gzip: function( cb ) {

			var count = this._files.length;
			var failed = false;

			this._files.forEach( function( file, index, array ) {
				action( 'Gzipping', base + file );
				zlib.gzip( fs.readFileSync( base + file ), function( err, buffer ) {

					if ( failed )
						return;
					else if ( err ) {
						failed = true;
						cb( err );
						return;
					}

					fs.writeFileSync( base + file, buffer );

					action( 'Gzipped', base + file + '.gzip' );

					if ( --count === 0 )
						cb();
				} );
			} );
		}
	};
};
<commit_msg>빌드 파일 마지막에 undefined가 붙는 버그 수정<commit_after>
/**
 * Cornerstone Framework Build Job
 */
var fs = require( 'fs' );
var zlib = require( 'zlib' );
var wrench = require( 'wrench' );
var glob = require( 'glob' );
var colorize = require( 'colorize' );
var jsp = require( 'uglify-js' ).parser;
var pro = require( 'uglify-js' ).uglify;
var less = require( 'less' );
var Step = require( 'step' );

const ENCODING = 'utf-8';

var log = exports.log = function( msg ) {
	msg ? colorize.console.log( msg ) : console.log();
};

var action = exports.action = function( action, file ) {

	// 줄맞춤을 위해 공백을 추가한다.
	const MAX_ACTION_LENGTH = 13;
	var actionLength = action.length;
	if ( actionLength < MAX_ACTION_LENGTH )
		for ( var i = 0; i < MAX_ACTION_LENGTH - actionLength; i++ ) action += ' ';

	colorize.console.log( '    - #cyan[(' + action + ')]: ' + file );
};

exports.mkdir = function( path ) {
	wrench.mkdirSyncRecursive( path );
	action( 'Created', path );
};

exports.copy = function( src, dest ) {
	wrench.copyDirSyncRecursive( src, dest );
	action( 'Copied', src + ' => ' + dest );
};

exports.concat = function() {

	var first = arguments[ 0 ];
	var last = arguments[ arguments.length - 1 ];
	var lastContent;

	try {
		lastContent = fs.readFileSync( last );
	}
	catch ( e ) {}

	action( 'Concatenating', first );
	fs.writeFileSync( last, fs.readFileSync( first ) );

	for ( var i = 1; i < arguments.length - 1; i++ ) {
		action( 'Concatenating', arguments[ i ] );
		fs.appendFileSync( last, fs.readFileSync( arguments[ i ] ) );
	}

	if ( lastContent ) {
		action( 'Concatenating', last );
		fs.appendFileSync( last, lastContent );
	}

	action( 'Concatenated', last );
};

exports.less = function( src, dest, cb ) {

	action( 'Compiling', src + ' => ' + dest );

	var parser = new( less.Parser )( {
		paths: [ src.substring( 0, src.lastIndexOf( '/' ) ) ]
	} );

	parser.parse( fs.readFileSync( src, ENCODING ), function( err, tree ) {
		if ( err ) {
			console.log( err );
			cb( err );
			return;
		}

		fs.writeFileSync( dest, tree.toCSS(), ENCODING );
		action( 'Compiled', src + ' => ' + dest );

		cb();
	} );
};

exports.files = function( base, pattern ) {

	return {

		// pattern에 맞는 파일명 목록 (base 부분을 제외한다.)
		_files: glob( base + pattern, { sync: true } ).map( function( file ) {
			return file.substring( 0, base.length ) === base ? file.substring( base.length ) : file;
		} ),

		// 삭제
		delete: function() {
			this._files.forEach( function( file, index, array ) {
				action( 'Deleting', base + file );
				fs.lstatSync( base + file ).isDirectory() ? wrench.rmdirSyncRecursive( base + file ) : fs.unlinkSync( base + file );
				action( 'Deleted', base + file );
			} );
		},

		// 최소화
		minify: function( dest ) {
			this._files.forEach( function( file, index, array ) {
				action( 'Minifying', base + file );
				var content = fs.readFileSync( base + file, ENCODING );
				var ast = jsp.parse( content );
				ast = pro.ast_mangle( ast );
				ast = pro.ast_squeeze( ast );
				fs.writeFileSync( dest + file, pro.gen_code( ast ), ENCODING );
				action( 'Minified', dest + file );
			} );
		},

		// gzip 압축
		gzip: function( cb ) {

			var count = this._files.length;
			var failed = false;

			this._files.forEach( function( file, index, array ) {
				action( 'Gzipping', base + file );
				zlib.gzip( fs.readFileSync( base + file ), function( err, buffer ) {

					if ( failed )
						return;
					else if ( err ) {
						failed = true;
						cb( err );
						return;
					}

					fs.writeFileSync( base + file, buffer );

					action( 'Gzipped', base + file + '.gzip' );

					if ( --count === 0 )
						cb();
				} );
			} );
		}
	};
};
<|endoftext|>