<commit_before>'use strict';
var
	global = global || window,
	jQuery = global.jQuery,
	React = global.React || require('react/addons'),
	cloneWithProps = React.addons.cloneWithProps,
	modules = [
		"accordion",
		"api",
		"checkbox",
		"colorize",
		"dimmer",
		"dropdown",
		"form",
		"modal",
		"dimmer",
		"nag",
		"popup",
		"progress",
		"rating",
		"search",
		"shape",
		"sidebar",
		"site",
		"state",
		"sticky",
		"tab",
		"transition",
		"video",
		"visibility",
		"visit"
	],
	moduleSearch = new RegExp('\\b(' + modules.join('|') + ')\\b', 'i');

/**
	@class Aui
	<Aui/> React Component for displaying Semantic UI,
	recursively queries it's children,
	copying all props that === true to the className,
	and handling things like basic dropdown logic as well.
	@example ```js
	var Page = React.createClass({
		render: function () {
			return (
				<Aui>
					<div ui page grid>
						<div column>
							<h1 ui centered header> Hello Page! </h1>
						</div>
					</div>
				</Aui>
			);
		}
	});
	React.render(<Page/>, document.body);

	// The dom should look something like this:
	<body>
		<div class="ui page grid">
			<div class="column">
				<h1 class="ui centered header"> Hello Page! </h1>
			</div>
		</div>
	</body>
	```
*/
var Aui = React.createClass({
  propTypes: {
    children: React.PropTypes.element.isRequired
  },
	render: function () {
		function query(Element) {
			if (Array.isArray(Element)) { return Element.map(query); }
			if (	React.isValidElement(Element) &&
						Element.props &&
						Element.props.noaui !== true &&
						Element.type !== Semantic) {
				var
					props = {
						className: Object.keys(Element.props)
							.filter(function (property) {
								return (Element.props[property] === true || moduleSearch.test(property));
							}).join(' '),
					};
				if (Element.key) { props.key = Element.key; }
				if (Element.ref) { props.ref = Element.ref; }
				if (Element.props.children) {
					props.children = query(Element.props.children);
					if (/\bform\b/.test(props.className) || /\bform\b/.test(Element.props.className)) {
						props.children = (
							Array.isArray(props.children) ?
								props.children :
								[props.children]);
						if (Element.props.onSubmit) {
							props.onFormSubmit = Element.props.onSubmit;
							props.onSubmit = null;
						}
						// normalize form submits:
						props.children.unshift(React.createElement('input', { type: 'submit', style: { display: 'none' } }));
					}
				}
				Element = cloneWithProps(Element, props);
				if (jQuery &&
						moduleSearch.test(Element.props.className) &&
						jQuery.fn[moduleSearch.exec(Element.props.className)[0]]) {
					return React.createElement(Semantic, { }, Element);
				}
			}
			return Element;
		};
		return query(this.props.children);
	},
});

var Semantic = React.createClass({
  propTypes: { children: React.PropTypes.element.isRequired },
	getInitialState: function () { return { formData: {} } },
	onFormInput: function (event) {
		var target = event.target;
		setTimeout(function () {
			var formData = this.state.formData;
			formData[target.name] = target.value;
			this.setState({ formData: formData });
		}.bind(this));
	},
	componentWillMount: function () {
		var onInput = this.props.children.props.onInput,
			onFormInput = this.onFormInput;
		this.bothFormOnInput = function (event) {
			onFormInput.apply(this, arguments);
			if (onInput) { onInput.apply(this, arguments); }
		}
	},
	render: function () {
		if (this.props.children.props.form) {
			return cloneWithProps(this.props.children, {
				onInput: this.bothFormOnInput
			});
		}
		return this.props.children;
	},
	componentDidMount: function () {
		var
			self = this,
			props = this.props.children.props,
			element = jQuery(this.getDOMNode()),
			bothFormOnInput = this.bothFormOnInput;
		function noop() {};
		function AuiSyntheticSyntheticEvent($target) {
			var target = (
				$target.filter('select,input')[0] ||
				$target.parents('.dropdown:first').find('select,input')[0] ||
				$target[0] ||
				element[0]);
			this.type = 'input';
			this.timeStamp = Date.now();
			this.target = target;
			this.preventDefault =
			this.isPersistent =
			this.isDefaultPrevented =
			this.isPropagationStopped =
			this.destructor =
			this.spotPropagation = noop;
		};
		if (props.name) { element.attr('data-name', props.name); }
		props.className.split(' ')
			.filter(function (moduleType) { return moduleSearch.test(moduleType); })
			.map(function (moduleType) {
				var settings = props[moduleType];
				if (!settings) { return; }
				settings = Array.isArray(settings) ? settings : [settings];
				var options = settings[settings.length-1] = settings[settings.length-1] || {};
				if (options === true) {
					options = settings[settings.length-1] = {};
				}
				if (moduleType === 'form') {
					if (!settings[1]) { settings[1] = {}; }
					if (props.onFormSubmit) {
						settings[1].onSuccess = function (event) {
							if (event.isTrigger) {
								event.data = self.state.formData;
								props.onFormSubmit.apply(this, arguments);
							} else {
								event.preventDefault();
							}
						};
					}
					options = settings[1];
					setTimeout(function () {
						element.find('[data-name]').each(function (_, input) {
							var
								$input = jQuery(input),
								data = self.state.formData;
							data[$input.attr('data-name')] = $input.val();
						});
					});
				}
				if (typeof options === 'object') {
					var onChange = options.onChange;
					Object.keys(props)
						.filter(function (key) { return /^on[A-Z]/.test(key); })
						.map(function (callback) {
							if (!/^on(Input|Change)$/.test(callback)) {
								options[callback] = props[callback];
							}
							element.data(callback, props[callback]);
						});
					if (moduleType === 'form') { element.data('onInput', bothFormOnInput); }
					options.onChange = function (_, value, $target) {
						if (onChange) { onChange.apply(this, arguments); }
						if (props.onInput) { props.onInput.call(this, new AuiSyntheticSyntheticEvent($target)); }
						if (props.onChange) { props.onChange.call(this, new AuiSyntheticSyntheticEvent($target)); }
						var form = $target.parents('.form:first');
						if (form[0]) {
							if (form.data('onChange')) { form.data('onChange').call(this, new AuiSyntheticSyntheticEvent($target)); }
							if (form.data('onInput')) { form.data('onInput').call(this, new AuiSyntheticSyntheticEvent($target)); }
						}
					};
				}
				element[moduleType].apply(element, settings);
				if (props.name) {
					setTimeout(function () {
						var formOnInput = element.parents('.form:first').data('onInput');
						if (formOnInput) {
							formOnInput(new AuiSyntheticSyntheticEvent(element));
						}
					});
				}
			});
	},
	componentWillUnmount: function () {
		jQuery(this.getDOMNode()).remove();
	},
});

if (!module) { var module = {}, exports; }
module.exports = exports = global.Aui = Aui;
exports.Aui = Aui;
exports.Semantic = Semantic;
if (jQuery) { exports.api = jQuery.fn.api; }
<commit_msg>enable behavior syntax for semantic modules<commit_after>'use strict';
var
	global = global || window,
	jQuery = global.jQuery,
	React = global.React || require('react/addons'),
	cloneWithProps = React.addons.cloneWithProps,
	modules = [
		"accordion",
		"api",
		"checkbox",
		"colorize",
		"dimmer",
		"dropdown",
		"form",
		"modal",
		"dimmer",
		"nag",
		"popup",
		"progress",
		"rating",
		"search",
		"shape",
		"sidebar",
		"site",
		"state",
		"sticky",
		"tab",
		"transition",
		"video",
		"visibility",
		"visit"
	],
	moduleSearch = new RegExp('\\b(' + modules.join('|') + ')\\b', 'i');

/**
	@class Aui
	<Aui/> React Component for displaying Semantic UI,
	recursively queries it's children,
	copying all props that === true to the className,
	and handling things like basic dropdown logic as well.
	@example ```js
	var Page = React.createClass({
		render: function () {
			return (
				<Aui>
					<div ui page grid>
						<div column>
							<h1 ui centered header> Hello Page! </h1>
						</div>
					</div>
				</Aui>
			);
		}
	});
	React.render(<Page/>, document.body);

	// The dom should look something like this:
	<body>
		<div class="ui page grid">
			<div class="column">
				<h1 class="ui centered header"> Hello Page! </h1>
			</div>
		</div>
	</body>
	```
*/
var Aui = React.createClass({
  propTypes: {
    children: React.PropTypes.element.isRequired
  },
	render: function () {
		function query(Element) {
			if (Array.isArray(Element)) { return Element.map(query); }
			if (	React.isValidElement(Element) &&
						Element.props &&
						Element.props.noaui !== true &&
						Element.type !== Semantic) {
				var
					props = {
						className: Object.keys(Element.props)
							.filter(function (property) {
								return (Element.props[property] === true || moduleSearch.test(property));
							}).join(' '),
					};
				if (Element.key) { props.key = Element.key; }
				if (Element.ref) { props.ref = Element.ref; }
				if (Element.props.children) {
					props.children = query(Element.props.children);
					if (/\bform\b/.test(props.className) || /\bform\b/.test(Element.props.className)) {
						props.children = (
							Array.isArray(props.children) ?
								props.children :
								[props.children]);
						if (Element.props.onSubmit) {
							props.onFormSubmit = Element.props.onSubmit;
							props.onSubmit = null;
						}
						// normalize form submits:
						props.children.unshift(React.createElement('input', { type: 'submit', style: { display: 'none' } }));
					}
				}
				Element = cloneWithProps(Element, props);
				if (jQuery &&
						moduleSearch.test(Element.props.className) &&
						jQuery.fn[moduleSearch.exec(Element.props.className)[0]]) {
					return React.createElement(Semantic, { }, Element);
				}
			}
			return Element;
		};
		return query(this.props.children);
	},
});

var Semantic = React.createClass({
  propTypes: { children: React.PropTypes.element.isRequired },
	getInitialState: function () { return { formData: {} } },
	onFormInput: function (event) {
		var target = event.target;
		setTimeout(function () {
			var formData = this.state.formData;
			formData[target.name] = target.value;
			this.setState({ formData: formData });
		}.bind(this));
	},
	componentWillMount: function () {
		var onInput = this.props.children.props.onInput,
			onFormInput = this.onFormInput;
		this.bothFormOnInput = function (event) {
			onFormInput.apply(this, arguments);
			if (onInput) { onInput.apply(this, arguments); }
		}
	},
	render: function () {
		if (this.props.children.props.form) {
			return cloneWithProps(this.props.children, {
				onInput: this.bothFormOnInput
			});
		}
		return this.props.children;
	},
	componentDidMount: function () {
		var
			self = this,
			props = this.props.children.props,
			element = jQuery(this.getDOMNode()),
			bothFormOnInput = this.bothFormOnInput;
		function noop() {};
		function AuiSyntheticSyntheticEvent($target) {
			var target = (
				$target.filter('select,input')[0] ||
				$target.parents('.dropdown:first').find('select,input')[0] ||
				$target[0] ||
				element[0]);
			this.type = 'input';
			this.timeStamp = Date.now();
			this.target = target;
			this.preventDefault =
			this.isPersistent =
			this.isDefaultPrevented =
			this.isPropagationStopped =
			this.destructor =
			this.spotPropagation = noop;
		};
		if (props.name) { element.attr('data-name', props.name); }
		props.className.split(' ')
			.filter(function (moduleType) { return moduleSearch.test(moduleType); })
			.map(function (moduleType) {
				var settings = props[moduleType];
				if (!settings) { return; }
				settings = Array.isArray(settings) ? settings : [settings];
				var options = settings[settings.length-1] = settings[settings.length-1] || {};
				if (options === true) {
					options = settings[settings.length-1] = {};
				}
				if (moduleType === 'form') {
					if (!settings[1]) { settings[1] = {}; }
					if (props.onFormSubmit) {
						settings[1].onSuccess = function (event) {
							if (event.isTrigger) {
								event.data = self.state.formData;
								props.onFormSubmit.apply(this, arguments);
							} else {
								event.preventDefault();
							}
						};
					}
					options = settings[1];
					setTimeout(function () {
						element.find('[data-name]').each(function (_, input) {
							var
								$input = jQuery(input),
								data = self.state.formData;
							data[$input.attr('data-name')] = $input.val();
						});
					});
				}
				if (typeof options === 'object') {
					var onChange = options.onChange;
					Object.keys(props)
						.filter(function (key) { return /^on[A-Z]/.test(key); })
						.map(function (callback) {
							if (!/^on(Input|Change)$/.test(callback)) {
								options[callback] = props[callback];
							}
							element.data(callback, props[callback]);
						});
					if (moduleType === 'form') { element.data('onInput', bothFormOnInput); }
					options.onChange = function (_, value, $target) {
						if (onChange) { onChange.apply(this, arguments); }
						if (props.onInput) { props.onInput.call(this, new AuiSyntheticSyntheticEvent($target)); }
						if (props.onChange) { props.onChange.call(this, new AuiSyntheticSyntheticEvent($target)); }
						var form = $target.parents('.form:first');
						if (form[0]) {
							if (form.data('onChange')) { form.data('onChange').call(this, new AuiSyntheticSyntheticEvent($target)); }
							if (form.data('onInput')) { form.data('onInput').call(this, new AuiSyntheticSyntheticEvent($target)); }
						}
					};
				}
				element[moduleType].apply(element, settings);
				if (props.name) {
					setTimeout(function () {
						var formOnInput = element.parents('.form:first').data('onInput');
						if (formOnInput) {
							formOnInput(new AuiSyntheticSyntheticEvent(element));
						}
					});
				}
			});
	},
	behaviors: {},
	shouldComponentUpdate: function () {
		var
			self = this,
			props = this.props.children.props,
			element = jQuery(this.getDOMNode());
		props.className.split(' ')
			.filter(function (moduleType) { return moduleSearch.test(moduleType); })
			.map(function (moduleType) {
				var behavior =
					(Array.isArray(props[moduleType]) ?
						props[moduleType] :
						[props[moduleType]]);
				if (typeof behavior[0] === 'string' && self.behaviors[moduleType] !== JSON.stringify(behavior)) {
					self.behaviors[moduleType] = JSON.stringify(behavior);
					console.log(moduleType, behavior);
					element[moduleType].apply(element, behavior);
				}
			});
		return true;
	},
	componentWillUnmount: function () {
		jQuery(this.getDOMNode()).remove();
	},
});

if (!module) { var module = {}, exports; }
module.exports = exports = global.Aui = Aui;
exports.Aui = Aui;
exports.Semantic = Semantic;
if (jQuery) { exports.api = jQuery.fn.api; }
<|endoftext|>


<commit_before>import meow from 'meow'
import Table from 'cli-table2'
import { stripIndent as strip } from 'common-tags'
import chalk from 'chalk'
import timeago from 'timeago.js'
import dockerps from './dockerps'

const cli = meow(`
  Usage
    $ dockerps [options]

  Options
    -a, --all         Show all containers (default shows just running)
    -n, --last <n>    Show n last created containers (includes non-running)
    -l, --latest      Show the latest created container (includes non-running)
    -v, --version     Print version
    -h, --help        Print usage
`,
  {
    alias: {
      a: 'all',
      l: 'latest',
      n: 'last',
      v: 'version',
      h: 'help'
    }
  }
)

const table = new Table({
  head: [chalk.blue('ID'), chalk.blue('Container'), chalk.blue('Status')],
  style: {
    head: []
  }
})

/* eslint-disable fp/no-mutation, no-param-reassign, complexity */
const flagsToDockerOptions = flags => {
  return Object.keys(flags).reduce((res, key) => {
    if (key === 'all') {
      res.all = flags[key]
    }

    if (key === 'latest') {
      res.limit = 1
    }

    if (key === 'last') {
      res.limit = flags[key]
    }

    return res
  }, {})
}
/* eslint-enable fp/no-mutation, no-param-reassign, complexity */

dockerps(flagsToDockerOptions(cli.flags)).then(containers => {
  if (containers.length === 0) {
    if (cli.flags.all) {
      console.log('no containers')
      process.exit(0)
    }
    console.log('no running containers')
    process.exit(0)
  }

  containers.forEach(container => {
    table.push([
      container.ports ? { rowSpan: 2, content: chalk.bold(container.id) } : chalk.bold(container.id),
      strip`
        ${chalk.magenta('Name')}
        ${container.name}
        ${chalk.magenta('Image')}
        ${container.image}
        ${chalk.magenta('Command')}
        ${container.command}`,
      strip`
        ${chalk.magenta('Created')}
        ${timeago().format(container.created * 1000)}
        ${chalk.magenta('State')}
        ${chalk.inverse(container.state)}
        ${chalk.magenta('Status')}
        ${container.status}`
    ])
    if (container.ports) {
      table.push([{
        content: `ports: ${container.ports}`,
        colSpan: 2,
        hAlign: 'center'
      }])
    }
  })
  console.log(table.toString())
  process.exit()
}).catch(e => {
  console.log(e)
  process.exit(1)
})
<commit_msg>ports enhance<commit_after>import meow from 'meow'
import Table from 'cli-table2'
import { stripIndent as strip } from 'common-tags'
import chalk from 'chalk'
import timeago from 'timeago.js'
import dockerps from './dockerps'

const cli = meow(`
  Usage
    $ dockerps [options]

  Options
    -a, --all         Show all containers (default shows just running)
    -n, --last <n>    Show n last created containers (includes non-running)
    -l, --latest      Show the latest created container (includes non-running)
    -v, --version     Print version
    -h, --help        Print usage
`,
  {
    alias: {
      a: 'all',
      l: 'latest',
      n: 'last',
      v: 'version',
      h: 'help'
    }
  }
)

const table = new Table({
  head: [chalk.blue('ID'), chalk.blue('Container'), chalk.blue('Status')],
  style: {
    head: []
  }
})

/* eslint-disable fp/no-mutation, no-param-reassign, complexity */
const flagsToDockerOptions = flags => {
  return Object.keys(flags).reduce((res, key) => {
    if (key === 'all') {
      res.all = flags[key]
    }

    if (key === 'latest') {
      res.limit = 1
    }

    if (key === 'last') {
      res.limit = flags[key]
    }

    return res
  }, {})
}
/* eslint-enable fp/no-mutation, no-param-reassign, complexity */

dockerps(flagsToDockerOptions(cli.flags)).then(containers => {
  if (containers.length === 0) {
    if (cli.flags.all) {
      console.log('no containers')
      process.exit(0)
    }
    console.log('no running containers')
    process.exit(0)
  }

  containers.forEach(container => {
    table.push([
      container.ports.length > 0 ? { rowSpan: 2, content: chalk.bold(container.id) } : chalk.bold(container.id),
      strip`
        ${chalk.magenta('Name')}
        ${container.name}
        ${chalk.magenta('Image')}
        ${container.image}
        ${chalk.magenta('Command')}
        ${container.command}`,
      strip`
        ${chalk.magenta('Created')}
        ${timeago().format(container.created * 1000)}
        ${chalk.magenta('State')}
        ${chalk.inverse(container.state)}
        ${chalk.magenta('Status')}
        ${container.status}`
    ])
    if (container.ports.length > 0) {
      table.push([{
        content: container.ports.join(', '),
        colSpan: 2,
        hAlign: 'center'
      }])
    }
  })
  console.log(table.toString())
  process.exit()
}).catch(e => {
  console.log(e)
  process.exit(1)
})
<|endoftext|>


<commit_before>#!/usr/bin/env node

import meow from "meow";
import path from "path";
import fs from "fs-extra";

import { error } from "./debug";
import Version from "./Version";

const cli = meow(`
  Usage:
    $ github-semantic-version

  Options:
    --init        Generates a new changelog and updates the current version in package.json.
    --bump        Bump the version in package.json based on the last change.
    --changelog   Bump the version in package.json AND append last change to the CHANGELOG.md.
    --push        Commits and pushes the changes (version and CHANGELOG) to the repo.
    --publish     Commits and pushes the changes to the repo, AND publishes the latest to NPM.
    --branch      (Default: master) Release branch, others are ignored.
    --force       By default, --bump and --changelog only work in CI environment. Override this only if you know what you're doing!
    --debug       Output debug info about what's happening in the running process.
    --dry-run     Perform a dry-run without writing, commiting, pushing, or publishing.
`, {

  default: Version.defaultOptions,
});

// we really need a GI_TOKEN or GITHUB_TOKEN b/c api request limiting
if (!(process.env.GI_TOKEN || process.env.GITHUB_TOKEN)) {
  error(`Either a GITHUB_TOKEN or GI_TOKEN environment variable is required to interact with the Github API.`);
  process.exit(1);
}

// if the user is publishing to NPM, they need an NPM_TOKEN
if (cli.flags.publish && !process.env.NPM_TOKEN) {
  error(`If specifying --publish, the NPM_TOKEN environment variable needs to be set.`);
  process.exit(1);
}

const validEnvironment = process.env.CI || cli.flags.force || cli.flags.dryRun;
const hasRequiredFlags = cli.flags.init || cli.flags.bump || cli.flags.changelog;

const packageOptions = getOptionsFromFile("./package.json");
const configOptions = packageOptions.gsv || getOptionsFromFile("./gsv.json");

if (!configOptions || !(configOptions["major-label"] && configOptions["minor-label"] && configOptions["patch-label"])) {
  error(`Must specify version label config options in either a gsv.json file or a package.json entry.
    Ex:
    {
      "major-label": "Version: Major",
      "minor-label": "Version: Minor",
      "patch-label": "Version: Patch"
    }
  `);
  process.exit(1);
}

const versionOptions = {
  version: packageOptions.version,
  private: packageOptions.private || false,
  ...configOptions
};

// run release only in CI environment. don't run complete changelog generation in CI.
if (validEnvironment && hasRequiredFlags) {
  const version = new Version(versionOptions, cli.flags);

  if (cli.flags.init) {
    version.refresh();
  } else {
    version.release();
  }
} else if (validEnvironment && !hasRequiredFlags) {
  error("Must specify one of the following options: --init, --bump, or --changelog")
  cli.showHelp(1);
} else {
  error("Not in CI environment or incorrect usage.");
  cli.showHelp(1);
}

function getOptionsFromFile(configFilePath) {
  if (configFilePath) {
    try {
      const filePath = path.resolve(process.cwd(), configFilePath);
      return fs.readJsonSync(filePath);
    } catch (err) {}
  }
}
<commit_msg>fixes GH_TOKEN typo<commit_after>#!/usr/bin/env node

import meow from "meow";
import path from "path";
import fs from "fs-extra";

import { error } from "./debug";
import Version from "./Version";

const cli = meow(`
  Usage:
    $ github-semantic-version

  Options:
    --init        Generates a new changelog and updates the current version in package.json.
    --bump        Bump the version in package.json based on the last change.
    --changelog   Bump the version in package.json AND append last change to the CHANGELOG.md.
    --push        Commits and pushes the changes (version and CHANGELOG) to the repo.
    --publish     Commits and pushes the changes to the repo, AND publishes the latest to NPM.
    --branch      (Default: master) Release branch, others are ignored.
    --force       By default, --bump and --changelog only work in CI environment. Override this only if you know what you're doing!
    --debug       Output debug info about what's happening in the running process.
    --dry-run     Perform a dry-run without writing, commiting, pushing, or publishing.
`, {

  default: Version.defaultOptions,
});

// we really need a GH_TOKEN or GITHUB_TOKEN b/c api request limiting
if (!(process.env.GH_TOKEN || process.env.GITHUB_TOKEN)) {
  error(`Either a GITHUB_TOKEN or GI_TOKEN environment variable is required to interact with the Github API.`);
  process.exit(1);
}

// if the user is publishing to NPM, they need an NPM_TOKEN
if (cli.flags.publish && !process.env.NPM_TOKEN) {
  error(`If specifying --publish, the NPM_TOKEN environment variable needs to be set.`);
  process.exit(1);
}

const validEnvironment = process.env.CI || cli.flags.force || cli.flags.dryRun;
const hasRequiredFlags = cli.flags.init || cli.flags.bump || cli.flags.changelog;

const packageOptions = getOptionsFromFile("./package.json");
const configOptions = packageOptions.gsv || getOptionsFromFile("./gsv.json");

if (!configOptions || !(configOptions["major-label"] && configOptions["minor-label"] && configOptions["patch-label"])) {
  error(`Must specify version label config options in either a gsv.json file or a package.json entry.
    Ex:
    {
      "major-label": "Version: Major",
      "minor-label": "Version: Minor",
      "patch-label": "Version: Patch"
    }
  `);
  process.exit(1);
}

const versionOptions = {
  version: packageOptions.version,
  private: packageOptions.private || false,
  ...configOptions
};

// run release only in CI environment. don't run complete changelog generation in CI.
if (validEnvironment && hasRequiredFlags) {
  const version = new Version(versionOptions, cli.flags);

  if (cli.flags.init) {
    version.refresh();
  } else {
    version.release();
  }
} else if (validEnvironment && !hasRequiredFlags) {
  error("Must specify one of the following options: --init, --bump, or --changelog")
  cli.showHelp(1);
} else {
  error("Not in CI environment or incorrect usage.");
  cli.showHelp(1);
}

function getOptionsFromFile(configFilePath) {
  if (configFilePath) {
    try {
      const filePath = path.resolve(process.cwd(), configFilePath);
      return fs.readJsonSync(filePath);
    } catch (err) {}
  }
}
<|endoftext|>


<commit_before>// Requirements
var autoprefixer = require('autoprefixer-core');
var fs = require('fs');
var svg2ttf = require('svg2ttf');
var ttf2woff = require('ttf2woff');
var shell = require('shelljs');

module.exports = function(grunt) {

	// Project configuration
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		sass: {
			options: {
				indentedSyntax: true,
			},
			main: {
				files: {
					'assets/temp/css/main.css': 'assets-src/css/main.sass',
				},
			},
			build: {
				options: {
					outputStyle: 'compressed',
				},
				files: {
					'assets/temp/css/main.css': 'assets-src/css/main.sass',
				},
			},
		},
		postcss: {
			options: {
				processors: [
					autoprefixer({ browsers: ['last 2 version'] }).postcss,
				],
			},
			main: {
				files: {
					'assets/css/main.css': 'assets/temp/css/main.css',
				},
			},
		},
		concat: {
			options: {
				separator: '\n;',
			},
			dist: {
				src: ['node_modules/jquery/dist/jquery.min.js', 'assets-src/js/script.js'],
				dest: 'assets/js/main.js',
			},
		},
		tinypng: {
			options: {
				apiKey: "INSERT TINYPNG API KEY",
				checkSigs: true,
				sigFile: 'assets/temp/image_md5s.json',
				summarize: true,
				showProgress: true,
				stopOnImageError: true
			},
			main: {
				files: [{
					expand: true,
					cwd: 'assets-src/images/',
					src: ['**/*.{png,jpg,gif}'],
					dest: 'assets/images/',
				}],
			},
		},
		copy: {
			fonts: {
				files: [{
					expand: true,
					cwd: 'assets-src/fonts/',
					src: ['*.{eot,svg,ttf,woff,woff2}'],
					dest: 'assets/fonts/',
				}],
			},
		},
	});

	// Grunt Tasks
	grunt.loadNpmTasks('grunt-sass');
	grunt.loadNpmTasks('grunt-postcss');
	grunt.loadNpmTasks('grunt-tinypng');
	grunt.loadNpmTasks('grunt-contrib-copy'); // currently not used
	grunt.loadNpmTasks('grunt-contrib-concat');

	grunt.registerTask('iconfont', 'Create icon font from SVG icons', function() {

		if (!fs.existsSync('assets/fonts')){
			fs.mkdirSync('assets/fonts');
		}

		shell.exec('vendor/bin/svg-icon-font-generator create-font --rename-files assets-src/fonts/icons assets/fonts/icons.svg');
		shell.exec('vendor/bin/svg-icon-font-generator create-info assets/fonts/icons.svg assets/fonts/icons.html');

		var ttf = svg2ttf(fs.readFileSync('assets/fonts/icons.svg', {encoding: 'utf-8'}), {});
		grunt.file.write('assets/fonts/icons.ttf', new Buffer(ttf.buffer));
		grunt.log.writeln('File "assets/fonts/icons.ttf" created.');

		var woff = ttf2woff(fs.readFileSync('assets/fonts/icons.ttf'), {});
		grunt.file.write('assets/fonts/icons.woff', new Buffer(woff.buffer));
		grunt.log.writeln('File "assets/fonts/icons.woff" created.');

	});

	// Custom Tasks
	grunt.registerTask('default', ['iconfont', 'sass:main', 'postcss', 'concat', 'tinypng', 'copy:fonts']);
	grunt.registerTask('build', ['iconfont', 'sass:build', 'postcss', 'concat', 'tinypng', 'copy:fonts']);

};
<commit_msg>Added watch command<commit_after>// Requirements
var autoprefixer = require('autoprefixer-core');
var fs = require('fs');
var svg2ttf = require('svg2ttf');
var ttf2woff = require('ttf2woff');
var shell = require('shelljs');

module.exports = function(grunt) {

	// Project configuration
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		sass: {
			options: {
				indentedSyntax: true,
			},
			main: {
				files: {
					'assets/temp/css/main.css': 'assets-src/css/main.sass',
				},
			},
			build: {
				options: {
					outputStyle: 'compressed',
				},
				files: {
					'assets/temp/css/main.css': 'assets-src/css/main.sass',
				},
			},
		},
		postcss: {
			options: {
				processors: [
					autoprefixer({ browsers: ['last 2 version'] }).postcss,
				],
			},
			main: {
				files: {
					'assets/css/main.css': 'assets/temp/css/main.css',
				},
			},
		},
		concat: {
			options: {
				separator: '\n;',
			},
			dist: {
				src: ['node_modules/jquery/dist/jquery.min.js', 'assets-src/js/script.js'],
				dest: 'assets/js/main.js',
			},
		},
		tinypng: {
			options: {
				apiKey: "INSERT TINYPNG API KEY",
				checkSigs: true,
				sigFile: 'assets/temp/image_md5s.json',
				summarize: true,
				showProgress: true,
				stopOnImageError: true
			},
			main: {
				files: [{
					expand: true,
					cwd: 'assets-src/images/',
					src: ['**/*.{png,jpg,gif}'],
					dest: 'assets/images/',
				}],
			},
		},
		copy: {
			fonts: {
				files: [{
					expand: true,
					cwd: 'assets-src/fonts/',
					src: ['*.{eot,svg,ttf,woff,woff2}'],
					dest: 'assets/fonts/',
				}],
			},
		},
		watch: {
			sass: {
				files: ['assets-src/css/*.sass'],
				tasks: ['sass:main', 'postcss'],
			},
			images: {
				files: ['assets-src/images/**/*'],
				tasks: ['tinypng', 'sass:main', 'postcss'],
			},
			js: {
				files: ['assets-src/js/**/*', '!assets-src/js/main.js'],
				tasks: ['jshint', 'concat'],
			},
			livereload: {
				files: [
					'assets/**/*',
					'!assets/temp/**/*',
					'content/**/*.md',
					'site/**/*',
					'!site/cache/*',
				],
				options: {
					livereload: true,
				},
			},
		},
		jshint: {
			files: ['assets-src/js/script.js'],
			options: {
				laxbreak: true,
			},
		},
		clean: {
			assets: {
				src: [
					'assets/**/*',
					'!assets/images/*',
					'!assets/temp/image_md5s.json',
				],
				filter: 'isFile',
			},
			images: {
				src: [
					'assets/images/**/*',
				],
				filter: function(src) {
					return !grunt.file.exists('assets-src/' + src.substr(7));
				},
			},
			build: ['site/cache/**/*'],
		},
	});

	// Grunt Tasks
	grunt.loadNpmTasks('grunt-contrib-concat');
	grunt.loadNpmTasks('grunt-contrib-copy');
	grunt.loadNpmTasks('grunt-contrib-clean');
	grunt.loadNpmTasks('grunt-contrib-jshint');
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-postcss');
	grunt.loadNpmTasks('grunt-sass');
	grunt.loadNpmTasks('grunt-tinypng');

	grunt.registerTask('iconfont', 'Create icon font from SVG icons', function() {

		if (!fs.existsSync('assets/fonts')){
			fs.mkdirSync('assets/fonts');
		}

		shell.exec('vendor/bin/svg-icon-font-generator create-font --rename-files assets-src/fonts/icons assets/fonts/icons.svg');
		shell.exec('vendor/bin/svg-icon-font-generator create-info assets/fonts/icons.svg assets/fonts/icons.html');

		var ttf = svg2ttf(fs.readFileSync('assets/fonts/icons.svg', {encoding: 'utf-8'}), {});
		grunt.file.write('assets/fonts/icons.ttf', new Buffer(ttf.buffer));
		grunt.log.writeln('File "assets/fonts/icons.ttf" created.');

		var woff = ttf2woff(fs.readFileSync('assets/fonts/icons.ttf'), {});
		grunt.file.write('assets/fonts/icons.woff', new Buffer(woff.buffer));
		grunt.log.writeln('File "assets/fonts/icons.woff" created.');

	});

	// Custom Tasks
	grunt.registerTask('default', ['clean:assets', 'clean:images', 'iconfont', 'sass:main', 'postcss', 'concat', 'tinypng', 'copy:fonts']);
	grunt.registerTask('build', ['clean:assets', 'clean:images', 'iconfont', 'sass:build', 'postcss', 'concat', 'tinypng', 'copy:fonts', 'clean:build']);

};
<|endoftext|>


<commit_before>
/**
 * The following bash code gets the difference from the build website and the git repos website
 *
 * (diff <(git ls-files www | sort) <(find build/www -type f | sed 's/^build\///' | sort)) | grep -e '^>' | cut -c 2-
 */

module.exports = function(grunt) {
//	var path = require('path');

	require('load-grunt-config')(grunt, {
		// path to task.js files, defaults to grunt dir
//		configPath: path.join(process.cwd(), 'grunt'),

		// auto grunt.initConfig
		init: true,

		// data passed into config. Can use in strings with <%= data.property %>
		data: {
			dirnames: {
				app: 'app',
				compiled: 'compiled',
				dist: 'dist'
			}
		},

		// use different function to merge config files
//		mergeFunction: require('recursive-merge')

		// can optionally pass options to load-grunt-tasks.
		// If you set to false, it will disable auto loading tasks.
		loadGruntTasks: {

//			pattern: 'grunt-*',
			config: require('./package.json')
//			scope: 'devDependencies'
		}

		//can post process config object before it gets passed to grunt
//		postProcess: function(config) {},

		//allows to manipulate the config object before it gets merged with the data object
//		preMerge: function(config, data) {}
	});

	/**
	 * Compiles TypeScript
	 */
  grunt.registerTask('compilets', function() {
		grunt.task.run('clean:compiled');

		// Compile TypeScript
//		grunt.task.run(['force:on', 'ts', 'force:reset']);
		grunt.task.run(['ts', 'browserify', 'uglify']);

//		grunt.task.run(['browserify:dist', 'uglify:dist']);
	});

	/**
	 * Compiles Sass
	 */
  grunt.registerTask('compilesass', function() {
		grunt.task.run('clean:compiled');

		// Compile Sass
		grunt.task.run(['sass', 'cssmin', 'copy:csstodist']);
	});

	/**
	 * Compiles/updates project
	 */
  grunt.registerTask('compile', function() {
		grunt.task.run('compilets');
		grunt.task.run('compilesass');

		grunt.task.run('copy:html');
		grunt.task.run('copy:config');
	});

	/**
	 * Builds project to dist
	 */
  grunt.registerTask('build', function() {
		grunt.task.run('compile');

		grunt.task.run('copy:images');
		grunt.task.run('copy:lib');
	});

	/**
	 * Cleans dist first then builds the project
	 */
  grunt.registerTask('rebuild', function() {
		grunt.task.run('clean:dist');

		grunt.task.run('build');

		// Make sure files are good
//		grunt.task.run(["jshint"]);
	});

	/**
	 * Runs the project in a browser
	 */
  grunt.registerTask('run', function() {
		grunt.task.run('connect');
	});

	/**
	 * Deploys project to staging/production
	 */
  grunt.registerTask('deploy', function(type) {
		grunt.fatal('Incomplete');
	});
};<commit_msg>Build the project before running grunt task 'run', if not already built<commit_after>
/**
 * The following bash code gets the difference from the build website and the git repos website
 *
 * (diff <(git ls-files www | sort) <(find build/www -type f | sed 's/^build\///' | sort)) | grep -e '^>' | cut -c 2-
 */

module.exports = function(grunt) {
//	var path = require('path');

	require('load-grunt-config')(grunt, {
		// path to task.js files, defaults to grunt dir
//		configPath: path.join(process.cwd(), 'grunt'),

		// auto grunt.initConfig
		init: true,

		// data passed into config
		data: {
			dirnames: {
				app: 'app',
				compiled: 'compiled',
				dist: 'dist'
			}
		},

		// use different function to merge config files
//		mergeFunction: require('recursive-merge')

		// can optionally pass options to load-grunt-tasks.
		// If you set to false, it will disable auto loading tasks.
		loadGruntTasks: {

//			pattern: 'grunt-*',
			config: require('./package.json')
//			scope: 'devDependencies'
		}

		//can post process config object before it gets passed to grunt
//		postProcess: function(config) {},

		//allows to manipulate the config object before it gets merged with the data object
//		preMerge: function(config, data) {}
	});

	/**
	 * Compiles TypeScript
	 */
  grunt.registerTask('compilets', function() {
		grunt.task.run('clean:compiled');

		// Compile TypeScript
//		grunt.task.run(['force:on', 'ts', 'force:reset']);
		grunt.task.run(['ts', 'browserify', 'uglify']);

//		grunt.task.run(['browserify:dist', 'uglify:dist']);
	});

	/**
	 * Compiles Sass
	 */
  grunt.registerTask('compilesass', function() {
		grunt.task.run('clean:compiled');

		// Compile Sass
		grunt.task.run(['sass', 'cssmin', 'copy:csstodist']);
	});

	/**
	 * Compiles/updates project
	 */
  grunt.registerTask('compile', function() {
		grunt.task.run('compilets');
		grunt.task.run('compilesass');

		grunt.task.run('copy:html');
		grunt.task.run('copy:config');
	});

	/**
	 * Builds project to dist
	 */
  grunt.registerTask('build', function() {
		grunt.task.run('compile');

		grunt.task.run('copy:images');
		grunt.task.run('copy:lib');
	});

	/**
	 * Cleans dist first then builds the project
	 */
  grunt.registerTask('rebuild', function() {
		grunt.task.run('clean:dist');

		grunt.task.run('build');

		// Make sure files are good
//		grunt.task.run(["jshint"]);
	});

	/**
	 * Runs the project in a browser
	 */
  grunt.registerTask('run', function() {
		var distDir = grunt.config.dirnames.dist;

		if (!grunt.file.exists(distDir + '/index.html')) {
			grunt.task.run('build');
		}

		grunt.task.run('connect');
	});

	/**
	 * Deploys project to staging/production
	 */
  grunt.registerTask('deploy', function(type) {
		grunt.fatal('Incomplete');
	});
};<|endoftext|>


<commit_before>/*globals require, process */

(function () {
    'use strict';

    var reports = {},

    cli = require('commander'),
    fs = require('fs'),
    cr = require('./complexityReport'),
    check = require('check-types'),
    formatter,

    state = {
        reading: true,
        unread: 0,
        tooComplex: false
    };

    parseCommandLine();
    readSourceFiles();

    function parseCommandLine () {
        cli.
            usage('[options] <file...>').
            option(
                '-o, --output <file>',
                'specify an output file for the report'
            ).
            option(
                '-f, --format <format>',
                'specify the output format of the report'
            ).
            //option(
            //    '-lo, --logicalor',
            //    'disable complexity reporting of operator ||'
            //).
            //option(
            //    '-t, --ternary',
            //    'disable complexity reporting of operator ?:'
            //).
            //option(
            //    '-sc, --switchcase',
            //    'disable complexity reporting of switch statements'
            //).
            //option(
            //    '-fi, --forin',
            //    'enable complexity reporting of for...in statements'
            //).
            //option(
            //    '-tc, --trycatch',
            //    'enable complexity reporting of catch clauses'
            //).
            option(
                '-th, --threshold <complexity>',
                'specifify the per-function complexity threshold'
            );

        cli.parse(process.argv);

        if (check.isUnemptyString(cli.format) === false) {
            cli.format = 'plain';
        }

        formatter = require('./formats/' + cli.format);
    }

    function readSourceFiles () {
        var i;

        for (i = 0; i < cli.args.length; i += 1) {
            state.unread += 1;
            readSourceFile(cli.args[i]);
        }

        state.reading = false;
    }

    function readSourceFile (path) {
        fs.readFile(path, 'utf8', function (error, source) {
            if (error) {
                console.log('Fatal error: ' + error.message);
                process.exit(1);
            }

            getReport(path, source);

            finish();
        });
    }

    function getReport (path, source) {
        var report = cr.run(source);

        report.module = path;

        reports.push(report);
    }

    function finish () {
        state.unread -= 1;

        if (state.reading === false && state.unread === 0) {
            writeReport();
        }
    }

    function writeReport () {
        var formatted = formatter.format(reports);

        if (cli.output) {
            fs.writeFile(cli.output, formatted, 'utf8', function (error) {
                if (error) {
                    console.log('Fatal error: ' + error.message);
                    process.exit(1);
                }

                exit();
            });
        }
    }

    function exit () {
        // TODO: Refactor all the exity stuff
        // TODO: Refactor all the loggy stuff
        // TODO: Use Q

        if (state.tooComplex) {
            console.log('Complexity threshold breached');
            process.exit(1);
        }

        console.log('Done');
    }
}());

<commit_msg>Fix reports type.<commit_after>/*globals require, process */

(function () {
    'use strict';

    var reports = [],

    cli = require('commander'),
    fs = require('fs'),
    cr = require('./complexityReport'),
    check = require('check-types'),
    formatter,

    state = {
        reading: true,
        unread: 0,
        tooComplex: false
    };

    parseCommandLine();
    readSourceFiles();

    function parseCommandLine () {
        cli.
            usage('[options] <file...>').
            option(
                '-o, --output <file>',
                'specify an output file for the report'
            ).
            option(
                '-f, --format <format>',
                'specify the output format of the report'
            ).
            //option(
            //    '-lo, --logicalor',
            //    'disable complexity reporting of operator ||'
            //).
            //option(
            //    '-t, --ternary',
            //    'disable complexity reporting of operator ?:'
            //).
            //option(
            //    '-sc, --switchcase',
            //    'disable complexity reporting of switch statements'
            //).
            //option(
            //    '-fi, --forin',
            //    'enable complexity reporting of for...in statements'
            //).
            //option(
            //    '-tc, --trycatch',
            //    'enable complexity reporting of catch clauses'
            //).
            option(
                '-th, --threshold <complexity>',
                'specifify the per-function complexity threshold'
            );

        cli.parse(process.argv);

        if (check.isUnemptyString(cli.format) === false) {
            cli.format = 'plain';
        }

        formatter = require('./formats/' + cli.format);
    }

    function readSourceFiles () {
        var i;

        for (i = 0; i < cli.args.length; i += 1) {
            state.unread += 1;
            readSourceFile(cli.args[i]);
        }

        state.reading = false;
    }

    function readSourceFile (path) {
        fs.readFile(path, 'utf8', function (error, source) {
            if (error) {
                console.log('Fatal error: ' + error.message);
                process.exit(1);
            }

            getReport(path, source);

            finish();
        });
    }

    function getReport (path, source) {
        var report = cr.run(source);

        report.module = path;

        reports.push(report);
    }

    function finish () {
        state.unread -= 1;

        if (state.reading === false && state.unread === 0) {
            writeReport();
        }
    }

    function writeReport () {
        var formatted = formatter.format(reports);

        if (cli.output) {
            fs.writeFile(cli.output, formatted, 'utf8', function (error) {
                if (error) {
                    console.log('Fatal error: ' + error.message);
                    process.exit(1);
                }

                exit();
            });
        }
    }

    function exit () {
        // TODO: Refactor all the exity stuff
        // TODO: Refactor all the loggy stuff
        // TODO: Use Q

        if (state.tooComplex) {
            console.log('Complexity threshold breached');
            process.exit(1);
        }

        console.log('Done');
    }
}());

<|endoftext|>


<commit_before>/*
 * This module provides BEM (Block Element Modifier) related methods
 * These methods can be used as an abstraction to talk to the DOM
 * BEM is a CSS methodology separating blocks (block) from elements (__element) and modifiers (--modifier)
 * BEM examples: alert, alert--warning, form__button, form__button--disabled
 * @see https://en.bem.info/methodology/key-concepts/
 * @module
 */

/**
 * BEM class
 * Contains static methods with BEM abstraction to DOM manipulation
 * @class
 */
class BEM {
    /**
     * Get a node by BEM (Block Element Modifier) description
     * @param {string} block The outer block or component
     * @param {string} [element] An optional element within the outer block
     * @param {string} [modifier] An optional modifier or (e.g. state or theme) for a block/element
     * @returns {HTMLElement}
     */
    static getBEMNode(block, element, modifier) {
        let selector = `.${BEM.getBEMClassName(block, element, modifier)}`;
        return document.querySelector(selector);
    }

    /**
     * Get multiple nodes by BEM (Block Element Modifier) description
     * @param {string} block The outer block or component
     * @param {string} [element] An optional element within the outer block
     * @param {string} [modifier] An optional modifier or (e.g. state or theme) for a block/element
     * @returns {NodeList}
     */
    static getBEMNodes(block, element, modifier) {
        let selector = `.${BEM.getBEMClassName(block, element, modifier)}`;
        return document.querySelectorAll(selector);
    }

    /**
     * Get a child node by BEM (Block Element Modifier) description
     * @param {HTMLElement} node The parent node
     * @param {string} block The outer block or component
     * @param {string} [element] An optional element within the outer block
     * @param {string} [modifier] An optional modifier or (e.g. state or theme) for a block/element
     * @returns {HTMLElement}
     */
    static getChildBEMNode(node, block, element, modifier) {
        let selector = `.${BEM.getBEMClassName(block, element, modifier)}`;
        return node.querySelector(selector);
    }

    /**
     * Get a child node by BEM (Block Element Modifier) description
     * @param {HTMLElement} node The parent node
     * @param {string} block The outer block or component
     * @param {string} [element] An optional element within the outer block
     * @param {string} [modifier] An optional modifier or (e.g. state or theme) for a block/element
     * @returns {HTMLElement}
     */
    static getChildBEMNodes(node, block, element, modifier) {
        let selector = `.${BEM.getBEMClassName(block, element, modifier)}`;
        return node.querySelectorAll(selector);
    }

    /**
     * Get a BEM (Block Element Modifier) (CSS) selector
     * @param {string} block The outer block or component
     * @param {string} [element] An optional element within the outer block
     * @param {string} [modifier] An optional modifier or (e.g. state or theme) for a block/element
     * @returns {string}
     */
    static getBEMSelector(block, element, modifier) {
        let selector = '.' + BEM.getBEMClassName(block, element);

        if (modifier) {
            selector += '.' + BEM.getBEMClassName(block, element, modifier);
        }

        return selector;
    }

    /**
     * Get a BEM (Block Element Modifier) class name
     * @param {string} block The outer block or component
     * @param {string} [element] An optional element within the outer block
     * @param {string} [modifier] An optional modifier or (e.g. state or theme) for a block/element
     * @returns {string}
     */
    static getBEMClassName(block, element, modifier) {
        let className = block;

        if (element) {
            className += `__${element}`;
        }

        if (modifier) {
            className += `--${modifier}`;
        }

        return className;
    }

    /**
     * Add an additional class name with a specific modifier (--modifier) to a BEM (Block Element Modifier) element
     * A modifier class is created for each of the existing class names
     * Class names containing "--" (modifier pattern) are discarded
     * Double class names are prevented
     * @param {HTMLElement} node The block/element to append the class name to (block, block__element)
     * @param {string} modifier The name of the modifier (--name)
     * @param {boolean} [exp=true] Optional: If true: add the modifier
     */
    static addModifier(node, modifier, exp=true) {
        if (!exp) {
            return;
        }

        [].forEach.call(node.classList, classListItem => {
            // Discard class names containing "--" (modifier pattern)
            if (classListItem.match('--')) {
                return;
            }

            let modifierClassName = `${classListItem}--${modifier}`;

            // Prevent double class names
            if (node.classList.contains(modifierClassName)) {
                return;
            }

            node.classList.add(modifierClassName);
        });
    }

    /**
     * Remove all class names with a specific modifier (--modifier) from a BEM (Block Element Modifier) element
     * @param {HTMLElement} node The block/element to remove the class names from (block, block__element)
     * @param {string} modifier The name of the modifier (--name)
     * @param {boolean} [exp=true] Optional: If true: remove the modifier
     */
    static removeModifier(node, modifier, exp=true) {
        if (!exp) {
            return;
        }

        let regex = new RegExp(`--${modifier}$`, 'g');
        let classNames = [].filter.call(node.classList, className => !className.match(regex));
        node.className = classNames.join(' ');
    }

    /**
     * Toggles between addModifier() and removeModifier() based on the presence of modifier (--modifier)
     * Block/element names are NOT taken into account while matching
     * @param {HTMLElement} node The block/element to remove the class names from (block, block__element)
     * @param {string} modifier The name of the modifier (--name)
     * @param {boolean} [exp] Optional: If true: add the modifier, if false: remove the modifier
     */
    static toggleModifier(node, modifier, exp=!BEM.hasModifier(node, modifier)) {
        if (exp) {
            BEM.addModifier(node, modifier);
            return;
        }
        BEM.removeModifier(node, modifier);
    }

    /**
     * Returns whether node has modifier (--modifier)
     * Block/element names are NOT taken into account while matching
     * @param {HTMLElement} node The block/element to check
     * @param {string} modifier The name of the modifier (--name)
     * @returns {boolean}
     */
    static hasModifier(node, modifier) {
        let regex = new RegExp(`--${modifier}(?=\\s|$)`, 'g');  // Regex matching specific modifier
        return node.className.match(regex);
    }
}

export default BEM;
export { BEM };
<commit_msg>:bulb: - Update BEM.getChildBEMNodes() docstring. (#20)<commit_after>/*
 * This module provides BEM (Block Element Modifier) related methods
 * These methods can be used as an abstraction to talk to the DOM
 * BEM is a CSS methodology separating blocks (block) from elements (__element) and modifiers (--modifier)
 * BEM examples: alert, alert--warning, form__button, form__button--disabled
 * @see https://en.bem.info/methodology/key-concepts/
 * @module
 */

/**
 * BEM class
 * Contains static methods with BEM abstraction to DOM manipulation
 * @class
 */
class BEM {
    /**
     * Get a node by BEM (Block Element Modifier) description
     * @param {string} block The outer block or component
     * @param {string} [element] An optional element within the outer block
     * @param {string} [modifier] An optional modifier or (e.g. state or theme) for a block/element
     * @returns {HTMLElement}
     */
    static getBEMNode(block, element, modifier) {
        let selector = `.${BEM.getBEMClassName(block, element, modifier)}`;
        return document.querySelector(selector);
    }

    /**
     * Get multiple nodes by BEM (Block Element Modifier) description
     * @param {string} block The outer block or component
     * @param {string} [element] An optional element within the outer block
     * @param {string} [modifier] An optional modifier or (e.g. state or theme) for a block/element
     * @returns {NodeList}
     */
    static getBEMNodes(block, element, modifier) {
        let selector = `.${BEM.getBEMClassName(block, element, modifier)}`;
        return document.querySelectorAll(selector);
    }

    /**
     * Get a child node by BEM (Block Element Modifier) description
     * @param {HTMLElement} node The parent node
     * @param {string} block The outer block or component
     * @param {string} [element] An optional element within the outer block
     * @param {string} [modifier] An optional modifier or (e.g. state or theme) for a block/element
     * @returns {HTMLElement}
     */
    static getChildBEMNode(node, block, element, modifier) {
        let selector = `.${BEM.getBEMClassName(block, element, modifier)}`;
        return node.querySelector(selector);
    }

    /**
     * Get multiple child nodes by BEM (Block Element Modifier) description
     * @param {HTMLElement} node The parent node
     * @param {string} block The outer block or component
     * @param {string} [element] An optional element within the outer block
     * @param {string} [modifier] An optional modifier or (e.g. state or theme) for a block/element
     * @returns {NodeList}
     */
    static getChildBEMNodes(node, block, element, modifier) {
        let selector = `.${BEM.getBEMClassName(block, element, modifier)}`;
        return node.querySelectorAll(selector);
    }

    /**
     * Get a BEM (Block Element Modifier) (CSS) selector
     * @param {string} block The outer block or component
     * @param {string} [element] An optional element within the outer block
     * @param {string} [modifier] An optional modifier or (e.g. state or theme) for a block/element
     * @returns {string}
     */
    static getBEMSelector(block, element, modifier) {
        let selector = '.' + BEM.getBEMClassName(block, element);

        if (modifier) {
            selector += '.' + BEM.getBEMClassName(block, element, modifier);
        }

        return selector;
    }

    /**
     * Get a BEM (Block Element Modifier) class name
     * @param {string} block The outer block or component
     * @param {string} [element] An optional element within the outer block
     * @param {string} [modifier] An optional modifier or (e.g. state or theme) for a block/element
     * @returns {string}
     */
    static getBEMClassName(block, element, modifier) {
        let className = block;

        if (element) {
            className += `__${element}`;
        }

        if (modifier) {
            className += `--${modifier}`;
        }

        return className;
    }

    /**
     * Add an additional class name with a specific modifier (--modifier) to a BEM (Block Element Modifier) element
     * A modifier class is created for each of the existing class names
     * Class names containing "--" (modifier pattern) are discarded
     * Double class names are prevented
     * @param {HTMLElement} node The block/element to append the class name to (block, block__element)
     * @param {string} modifier The name of the modifier (--name)
     * @param {boolean} [exp=true] Optional: If true: add the modifier
     */
    static addModifier(node, modifier, exp=true) {
        if (!exp) {
            return;
        }

        [].forEach.call(node.classList, classListItem => {
            // Discard class names containing "--" (modifier pattern)
            if (classListItem.match('--')) {
                return;
            }

            let modifierClassName = `${classListItem}--${modifier}`;

            // Prevent double class names
            if (node.classList.contains(modifierClassName)) {
                return;
            }

            node.classList.add(modifierClassName);
        });
    }

    /**
     * Remove all class names with a specific modifier (--modifier) from a BEM (Block Element Modifier) element
     * @param {HTMLElement} node The block/element to remove the class names from (block, block__element)
     * @param {string} modifier The name of the modifier (--name)
     * @param {boolean} [exp=true] Optional: If true: remove the modifier
     */
    static removeModifier(node, modifier, exp=true) {
        if (!exp) {
            return;
        }

        let regex = new RegExp(`--${modifier}$`, 'g');
        let classNames = [].filter.call(node.classList, className => !className.match(regex));
        node.className = classNames.join(' ');
    }

    /**
     * Toggles between addModifier() and removeModifier() based on the presence of modifier (--modifier)
     * Block/element names are NOT taken into account while matching
     * @param {HTMLElement} node The block/element to remove the class names from (block, block__element)
     * @param {string} modifier The name of the modifier (--name)
     * @param {boolean} [exp] Optional: If true: add the modifier, if false: remove the modifier
     */
    static toggleModifier(node, modifier, exp=!BEM.hasModifier(node, modifier)) {
        if (exp) {
            BEM.addModifier(node, modifier);
            return;
        }
        BEM.removeModifier(node, modifier);
    }

    /**
     * Returns whether node has modifier (--modifier)
     * Block/element names are NOT taken into account while matching
     * @param {HTMLElement} node The block/element to check
     * @param {string} modifier The name of the modifier (--name)
     * @returns {boolean}
     */
    static hasModifier(node, modifier) {
        let regex = new RegExp(`--${modifier}(?=\\s|$)`, 'g');  // Regex matching specific modifier
        return node.className.match(regex);
    }
}

export default BEM;
export { BEM };
<|endoftext|>


<commit_before>module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    buildsrc: [
        'src/fossil-i18next.js'
    ],
    concurrent: {
        dev: {
            tasks: ['watch', 'connect:server:keepalive'],
            options: {
                logConcurrentOutput: true
            }
        }
    },
    watch: {
        src: {
            files: 'src/**/*.js',
            tasks: ['concat:library', 'contcat:amd']
        }
    },
    connect: {
        server: {
            options: {
                port: 8000,
                base: '.',
                hostname: '*'
            }
        }
    },
    mocha: {
        options: {
            log: true,
            ingnoreLeaks: false,
            reporter: 'Spec',
            run: true
        },
        all: ['tests/test.html']
    },
    concat: {
        library:{
            options: {
                banner: "(function (_, Fossil, Handlebars, i18next, jQuery) {\n",
                footer: [
                    "return Fossil.Services.I18next;",
                    "})(_, Fossil, Handlebars, i18n, jQuery);"
                ].join("\n")
            },
            src: '<%= buildsrc %>',
            dest: '<%= pkg.name %>.js'
        },
        amd:{
            options: {
                banner: [
                    "define('fossil-i18next', ",
                    "['underscore', 'fossil', 'handlebars', 'i18next', 'jquery'], ",
                    "function (_, Fossil, Handlebars, i18next, jQuery) {\n"
                ].join("\n"),
                footer: [
                    "return Fossil.Services.I18next;",
                    "});"
                ].join("\n")
            },
            src: '<%= buildsrc %>',
            dest: '<%= pkg.name %>-amd.js'
        }
    },
    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
      },
      library: {
        src: '<%= pkg.name %>.js',
        dest: '<%= pkg.name %>.min.js'
      },
      amd: {
        src: '<%= pkg.name %>-amd.js',
        dest: '<%= pkg.name %>-amd.min.js'
      }
    }
  });

  // Load the plugin that provides the "uglify" task.
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-concurrent');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-mocha');

  // Default task(s).
  grunt.registerTask('test', ['mocha']);
  grunt.registerTask('dev', ['concat:library', 'concat:amd', 'concurrent:dev']);
  grunt.registerTask('release', ['concat:library', 'concat:amd', 'test', 'uglify:library', 'uglify:amd']);
  grunt.registerTask('default', ['release']);

};
<commit_msg>Typo fix in Gruntfile.<commit_after>module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    buildsrc: [
        'src/fossil-i18next.js'
    ],
    concurrent: {
        dev: {
            tasks: ['watch', 'connect:server:keepalive'],
            options: {
                logConcurrentOutput: true
            }
        }
    },
    watch: {
        src: {
            files: 'src/**/*.js',
            tasks: ['concat:library', 'concat:amd']
        }
    },
    connect: {
        server: {
            options: {
                port: 8000,
                base: '.',
                hostname: '*'
            }
        }
    },
    mocha: {
        options: {
            log: true,
            ingnoreLeaks: false,
            reporter: 'Spec',
            run: true
        },
        all: ['tests/test.html']
    },
    concat: {
        library:{
            options: {
                banner: "(function (_, Fossil, Handlebars, i18next, jQuery) {\n",
                footer: [
                    "return Fossil.Services.I18next;",
                    "})(_, Fossil, Handlebars, i18n, jQuery);"
                ].join("\n")
            },
            src: '<%= buildsrc %>',
            dest: '<%= pkg.name %>.js'
        },
        amd:{
            options: {
                banner: [
                    "define('fossil-i18next', ",
                    "['underscore', 'fossil', 'handlebars', 'i18next', 'jquery'], ",
                    "function (_, Fossil, Handlebars, i18next, jQuery) {\n"
                ].join("\n"),
                footer: [
                    "return Fossil.Services.I18next;",
                    "});"
                ].join("\n")
            },
            src: '<%= buildsrc %>',
            dest: '<%= pkg.name %>-amd.js'
        }
    },
    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
      },
      library: {
        src: '<%= pkg.name %>.js',
        dest: '<%= pkg.name %>.min.js'
      },
      amd: {
        src: '<%= pkg.name %>-amd.js',
        dest: '<%= pkg.name %>-amd.min.js'
      }
    }
  });

  // Load the plugin that provides the "uglify" task.
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-concurrent');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-mocha');

  // Default task(s).
  grunt.registerTask('test', ['mocha']);
  grunt.registerTask('dev', ['concat:library', 'concat:amd', 'concurrent:dev']);
  grunt.registerTask('release', ['concat:library', 'concat:amd', 'test', 'uglify:library', 'uglify:amd']);
  grunt.registerTask('default', ['release']);

};
<|endoftext|>


<commit_before>var _ = require("lodash");

var argument = require("./argument");
var command = require("./command");
var option = require("./option");
var utils = require("./utils");

var cli = function(opts, cb) {
  var options = opts || {};
  var name = options.name || utils.getProcessName(process.argv);
  var description = options.description || "";
  var flags = options.options || [];
  var commands = options.commands || [];
  var args = options.args || [];
  var action = typeof cb !== 'undefined' ? cb : null;
  return {
    getValue: function(cliArgs, cliOpts) {
      var parsedOptions = option.parseOptions(flags, cliOpts);

      if(utils.isValid(parsedOptions)) {
        var matchedCommand = _.find(commands, function(command) {
          return command.name === cliArgs[0];
        });

        if(matchedCommand) {
          var commandResult = matchedCommand.getValue(_.drop(cliArgs, 1), cliOpts, parsedOptions.success);
          if(utils.isError(commandResult)) {
            console.log(matchedCommand.helpText(name));
          }
        } else {
          var parsedArgs = argument.parseArgs(args, cliArgs);

          if(action !== null && utils.isValid(parsedArgs)) {
              action({
                args: parsedArgs.success,
                options: parsedOptions.success
              });
          } else {
            console.log(this.helpText);
          }
        }
      } else {
        console.log(this.helpText);
      }

    },
    helpText: function() {
      var optionsText = option.availableOptionsText(flags);
      var commandsText = command.availableCommandsText(commands);

      var output = name;
      if(description) output += ": " + description;
      output += '\n';
      if(!_.isEmpty(args)) output += "\nUsage : " + name + _.pluck(args, "helpText").join(' ');
      if(optionsText) output += '\n' + optionsText;
      if(optionsText && commandsText) output += '\n';
      if(commandsText) output += '\n' + commandsText;

      return output;
    }()
  };
};

module.exports = {
  cli: cli
};
<commit_msg>Fix `Usage` text for top-level applications<commit_after>var _ = require("lodash");

var argument = require("./argument");
var command = require("./command");
var option = require("./option");
var utils = require("./utils");

var cli = function(opts, cb) {
  var options = opts || {};
  var name = options.name || utils.getProcessName(process.argv);
  var description = options.description || "";
  var flags = options.options || [];
  var commands = options.commands || [];
  var args = options.args || [];
  var action = typeof cb !== 'undefined' ? cb : null;
  return {
    getValue: function(cliArgs, cliOpts) {
      var parsedOptions = option.parseOptions(flags, cliOpts);

      if(utils.isValid(parsedOptions)) {
        var matchedCommand = _.find(commands, function(command) {
          return command.name === cliArgs[0];
        });

        if(matchedCommand) {
          var commandResult = matchedCommand.getValue(_.drop(cliArgs, 1), cliOpts, parsedOptions.success);
          if(utils.isError(commandResult)) {
            console.log(matchedCommand.helpText(name));
          }
        } else {
          var parsedArgs = argument.parseArgs(args, cliArgs);

          if(action !== null && utils.isValid(parsedArgs)) {
              action({
                args: parsedArgs.success,
                options: parsedOptions.success
              });
          } else {
            console.log(this.helpText);
          }
        }
      } else {
        console.log(this.helpText);
      }

    },
    helpText: function() {
      var optionsText = option.availableOptionsText(flags);
      var commandsText = command.availableCommandsText(commands);

      var output = name;
      if(description) output += ": " + description;
      output += '\n';
      if(!_.isEmpty(args)) output += "\nUsage : " + name + " " + _.pluck(args, "helpText").join(' ');
      if(optionsText) output += '\n\n' + optionsText;
      if(optionsText && commandsText) output += '\n';
      if(commandsText) output += '\n' + commandsText;

      return output;
    }()
  };
};

module.exports = {
  cli: cli
};
<|endoftext|>


<commit_before>let doc = `
Usage: sassdoc <src> <dest> [options]

Arguments:
  <src>   Path to your Sass folder.
  <dest>  Path to the destination folder.

Options:
  -h, --help            Bring help.
  --version             Show version.
  -v, --verbose         Enable verbose mode.
  -i, --interactive     Prompt to remove an existing destination directory.
  -f, --force           Always remove an existing destination directory
                        without asking.
  -c, --config=<path>   Path to JSON/YAML configuration file.
  -t, --theme=<name>    Theme to use.
  --sass-convert        Use if syntax is ".sass".
  --no-update-notifier  Disable update notifier check.
`;

let docopt = require('docopt').docopt;
let pkg = require('../package.json');
let cfg = require('./cfg');
let Logger = require('./logger').default;
let sassdoc = require('./sassdoc').default;

export default function (argv = process.argv) {
  let options = docopt(doc, { version: pkg.version, argv: argv });
  let logger = new Logger(options['--verbose']);

  // Load raw configuration
  let config = cfg.pre(options['--config'] || undefined, logger);

  // Ensure CLI options
  ensure(config, options, {
    theme: '--theme',
    interactive: '--interactive',
    force: '--force',
    sassConvert: '--sass-convert',
    noUpdateNotifier: '--no-update-notifier',
  });

  // Post process configuration
  cfg.post(config);

  config.view = config; // Backward compatibility

  // Run update notifier if not explicitely disabled
  if (!config.noUpdateNotifier) {
    require('./notifier').default(pkg, logger);
  }

  sassdoc(options['<src>'], options['<dest>'], config);
}

/**
 * Ensure that CLI options take precedence over configuration values.
 *
 * For each name/option tuple, if the option is set, override configuration
 * value.
 */
function ensure(config, options, names) {
  Object.keys(names).forEach(k => {
    let v = names[k];

    if (options[v]) {
      config[k] = options[v];
    }
  });
}
<commit_msg>Remove `--sass-convert` option from cli<commit_after>let doc = `
Usage: sassdoc <src> <dest> [options]

Arguments:
  <src>   Path to your Sass folder.
  <dest>  Path to the destination folder.

Options:
  -h, --help            Bring help.
  --version             Show version.
  -v, --verbose         Enable verbose mode.
  -i, --interactive     Prompt to remove an existing destination directory.
  -f, --force           Always remove an existing destination directory
                        without asking.
  -c, --config=<path>   Path to JSON/YAML configuration file.
  -t, --theme=<name>    Theme to use.
  --no-update-notifier  Disable update notifier check.
`;

let docopt = require('docopt').docopt;
let pkg = require('../package.json');
let cfg = require('./cfg');
let Logger = require('./logger').default;
let sassdoc = require('./sassdoc').default;

export default function (argv = process.argv) {
  let options = docopt(doc, { version: pkg.version, argv: argv });
  let logger = new Logger(options['--verbose']);

  // Load raw configuration
  let config = cfg.pre(options['--config'] || undefined, logger);

  // Ensure CLI options
  ensure(config, options, {
    theme: '--theme',
    interactive: '--interactive',
    force: '--force',
    noUpdateNotifier: '--no-update-notifier',
  });

  // Post process configuration
  cfg.post(config);

  config.view = config; // Backward compatibility

  // Run update notifier if not explicitely disabled
  if (!config.noUpdateNotifier) {
    require('./notifier').default(pkg, logger);
  }

  sassdoc(options['<src>'], options['<dest>'], config);
}

/**
 * Ensure that CLI options take precedence over configuration values.
 *
 * For each name/option tuple, if the option is set, override configuration
 * value.
 */
function ensure(config, options, names) {
  Object.keys(names).forEach(k => {
    let v = names[k];

    if (options[v]) {
      config[k] = options[v];
    }
  });
}
<|endoftext|>


<commit_before>'use strict';

var path = require('path');

module.exports = function (grunt) {

  grunt.initConfig({

   "git-describe": {
      options: {
          cwd: '.'
      },
      target: {
      },
    },

    express: {
      server: {
        options: {
          port: 8080,
          bases: path.resolve(__dirname)
        }
      },
      livereload: true
    },

    requirejs: {
      chromeApp: {
        options: {
          mainConfigFile: './require_config.js',
          include: ['../chrome-app/extended-config','ReadiumViewer'],
          name: 'thirdparty/almond',
          baseUrl: './lib/',
          optimize: 'none',
          out: 'build/chrome-app/scripts/readium-all.js',
          paths: {
            'i18n/Strings': '../chrome-app/i18n/Strings',
            'storage/StorageManager' : '../chrome-app/storage/FileSystemStorage',
            'storage/Settings' : '../chrome-app/storage/ChromeSettings',
            'analytics/Analytics' : '../chrome-app/analytics/ExtensionAnalytics',
            'google-analytics-bundle' : '../chrome-app/analytics/google-analytics-bundle'

          },
          shim: {
            'google-analytics-bundle' : {
              exports: 'analytics'
            }
          }
        }
      },
      chromeAppWorker : {
        options : {
          mainConfigFile: './require_config.js',
          include: ['workers/EpubLibraryWriter'],
          name: 'thirdparty/almond',
          baseUrl: './lib/',
          optimize: 'none',
          out: 'build/chrome-app/scripts/readium-worker.js',
          paths: {
            'i18n/Strings': '../chrome-app/i18n/Strings',
            'storage/StorageManager' : '../chrome-app/storage/FileSystemStorage'
          }
        }
      },
      cloudReader : {
        options: {
          mainConfigFile: './require_config.js',
          include: ['ReadiumViewer'],
          name: 'thirdparty/almond',
          baseUrl: './lib/',
          out: 'build/cloud-reader/scripts/readium-all.js'
        }
      }
    },
    cssmin : {
        chromeApp : {
            files : {
              'build/chrome-app/css/readium-all.css' : ['css/sourcesanspro.css', 'css/bootstrap.css', 'css/readium_js.css', 'css/viewer.css', 'css/library.css']
            }
        },
        cloudReader: {
            files : {
              'build/cloud-reader/css/readium-all.css' : ['css/sourcesanspro.css', 'css/bootstrap.css', 'css/readium_js.css', 'css/viewer.css', 'css/library.css']
            }
        }
    },

    copy : {
      chromeApp: {
        files: [
            {expand: true, cwd: 'chrome-app/', src: ['icons/*.*', 'index.html', 'background.js', 'extended-config.js', 'manifest.json'], dest: 'build/chrome-app'},
            {expand: true, src: 'images/**', dest: 'build/chrome-app'},
            {expand: true, cwd: 'i18n', src: '_locales/**', dest: 'build/chrome-app'},
            {expand: true, cwd: 'lib/thirdparty/', src: ['inflate.js', 'deflate.js'], dest:'build/chrome-app'},
            {expand: true, cwd: 'css', src: 'annotations.css', dest: 'build/chrome-app/css'},
            {expand: true, src: 'fonts/**', dest: 'build/chrome-app'}
        ]
      },
      chromeAppDevBuild: {
        files: [
            {expand: false, cwd: 'chrome-app/icons/devBuild/', src: ['*.*'], dest: 'build/chrome-app/icons/'
            /* , rename: function(dest, src) { return dest + '/' + src } */
            }
        ]
      },
      cloudReader: {
        files: [
          {expand: true, cwd: 'chrome-app/', src: 'index.html', dest: 'build/cloud-reader'},
          {expand: true, src: 'images/**', dest: 'build/cloud-reader'},
          {expand: true, src: 'fonts/**', dest: 'build/cloud-reader'},
          {expand: true, cwd: 'css', src: 'annotations.css', dest: 'build/cloud-reader/css'},
        ]
      },
      cloudReaderEpubContent: {
        files: [
          {expand: true, src: 'epub_content/**/*.*', dest: 'build/cloud-reader'}
        ]
      },
      readiumjs: {
        files: [
          {expand: true, cwd: 'readium-js/out/', src: 'Readium.js', dest: 'lib'}
        ]
      },
      prepareChromeAppTests: {
        files: [
          {expand: true, cwd: 'chrome-app/tests/', src: 'manifest.json', dest: 'build/chrome-app'}
        ]
      }
    },
    nodeunit: {
      chromeApp: ['chrome-app/tests/tests.js']
    },
    clean : {
      chromeApp: ['build/chrome-app'],
      cloudReader: ['build/cloud-reader']
    },
    run_grunt: {
      readiumjs : {
        options: {
          cwd: 'readium-js'
        },
        src: 'readium-js/Gruntfile.js'
      }
    },
    watch : {
      readiumjs:{
        files: ['readium-js/**/*.js','!readium-js/out/Readium.js','!readium-js/**/node_modules/**'],
        tasks: ['update-readium']
      }
    },
    concurrent : {
      serverwatch : {
        tasks: ['runserver', 'watch:readiumjs'],
        options: {
          logConcurrentOutput: true
        }
      }
    }

  });

  grunt.loadNpmTasks('grunt-express');

  grunt.loadNpmTasks('grunt-contrib-requirejs');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-nodeunit');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-run-grunt');
  grunt.loadNpmTasks('grunt-concurrent');

  grunt.loadNpmTasks('grunt-git-describe');

  grunt.registerTask('runserver', ['express', 'express-keepalive']);
  grunt.registerTask('default', 'concurrent:serverwatch');
  grunt.registerTask('update-readium', ['run_grunt:readiumjs', 'copy:readiumjs']);
  grunt.registerTask('test', ['chromeApp', 'copy:prepareChromeAppTests', 'nodeunit:chromeApp']);

  grunt.registerTask('chromeApp', ['clean:chromeApp', 'copy:chromeApp', 'cssmin:chromeApp', 'requirejs:chromeApp', 'requirejs:chromeAppWorker']);

  grunt.registerTask('cloudReader', ['clean:cloudReader', 'copy:cloudReader', 'cssmin:cloudReader', 'requirejs:cloudReader']);
  grunt.registerTask('cloudReaderWithEpub', ['clean:cloudReader', 'copy:cloudReader', 'copy:cloudReaderEpubContent', 'cssmin:cloudReader', 'requirejs:cloudReader']);

  grunt.registerTask('devBuildManifest', function() {
       var manifest = require('./build/chrome-app/manifest.json');

       manifest.description = manifest.description + " (DEV BUILD)";
       manifest.version = manifest.version + ".999";

       var fs = require('fs');
       fs.writeFileSync('./build/chrome-app/manifest.json', JSON.stringify(manifest, null, 2));
  });
  grunt.registerTask('chromeAppDevBuild', [ 'chromeApp', 'copy:chromeAppDevBuild', 'devBuildManifest']);

  //Populates the EPUB3 navigator.epubReadingSystem with versioning information for each Readium component / dependency.
  //This data gets serialised to a JSON file,
  //which should then be pulled by shared_js/readium_sdk.js
  //(because ReadiumSDK creates the app-level navigator.epubReadingSystem object)
  //Normally, the navigator.epubReadingSystem object is "customised" in EpubReader.js (with the correct 'name' and 'version' fields),
  //but this could be done in this build step (i.e. the generated epubReadingSystem.json file is "ready", not need for further customisation)
  //Note that subsequently, the navigator.epubReadingSystem is "forwarded" to each EPUB Content Document's host iframe (see shared_js/iframe_loader.js)
  // Also note that navigator.epubReadingSystem.hasFeature is a Javascript function (taking the parameters "feature" and "version")
  // so it cannot be serialised to JSON (it would just be a string). It therefore has to be defined in a JS file,
  // perhaps shared_js/readium_sdk.js (default baseline), and/or EpubReader.js (customised)

  grunt.registerTask('epubReadingSystem_gitDescribe', function(fullPath) {
grunt.log.writeln("Module directory: " + fullPath);

    var module = grunt.option('epubReadingSystem_moduleMap_' + fullPath);
    //var module = grunt.config.get(["git-describe", "options", "moduleMap", fullPath]);
//grunt.log.writeln("module: " + module);

    //TODO: decide whether to grab info from package.json, or from the computed module info (in which case version comes from Git revision)
    var packageJson = fullPath + '/package.json';
    if (grunt.file.exists(packageJson)) {
        var pack = grunt.file.readJSON(packageJson);
        module.name = pack.name;
        module.version = pack.version;

        if (pack.title || pack.description) {
            module.description = pack.title + " -- " + pack.description;
        }
    }

    grunt.event.once('git-describe', function (rev) {
//grunt.log.writeln("Git Revision: " + rev);

          //grunt.option('gitRevision', rev);
          //var rev = grunt.option('gitRevision');

grunt.log.writeln("Git rev tag: " + rev.tag);
grunt.log.writeln("Git rev since: " + rev.since);
grunt.log.writeln("Git rev object: " + rev.object);
grunt.log.writeln("Git rev dirty: " + rev.dirty);

        module["url_tag"] = module.url + "releases/tag/" + rev.tag;
        module["url_hash"] = module.url + "tree/" + rev.object;

        module.version = rev.tag;
        module.hash = rev.object;

        module.modules = module.modules;
      });

      grunt.config.set(["git-describe", "options", "cwd"], fullPath);
      grunt.task.run('git-describe');
  });

  grunt.registerTask('epubReadingSystem_readJSON', function() {

      //var epubReadingSystem = grunt.file.readJSON('./epubReadingSystem.json');
      var epubReadingSystem = require('./epubReadingSystem.json');

      grunt.option('epubReadingSystem_JSON', epubReadingSystem);
  });

  grunt.registerTask('epubReadingSystem_writeJSON', function() {

      var epubReadingSystem = grunt.option('epubReadingSystem_JSON');

       epubReadingSystem.readium.date = grunt.template.today();

       //TODO: decide whether to grab info from package.json, or from the computed module info (in which case version comes from Git revision)
       var pack = grunt.file.readJSON('package.json');
       epubReadingSystem.name = pack.name;
       epubReadingSystem.version = pack.version;

       epubReadingSystem.name = epubReadingSystem.readium.modules[0].name;
       epubReadingSystem.version = epubReadingSystem.readium.modules[0].version;

       // TODO this gets done in shared_js/readium_sdk.js or EpubReader.js
       //epubReadingSystem.hasFeature = eval(epubReadingSystem.hasFeature);

       var jSon = JSON.stringify(epubReadingSystem, null, 2);
grunt.log.writeln(jSon);

       grunt.file.write('./build/epubReadingSystem.json', jSon);
       // var fs = require('fs');
       // fs.writeFileSync(...);
  });

  grunt.registerTask('epubReadingSystem_processModules', function() {

      Array.isArray = Array.isArray || function (obj) {
          return Object.prototype.toString.call(obj) === "[object Array]";
      };

      var processModules = function(basePath, json)
      {
          for (var prop in json)
          {
              if (!json.hasOwnProperty(prop)) continue;

              if (prop === "modules" && Array.isArray(json[prop]))
              {
                  for (var i = 0; i < json[prop].length; i++)
                  {
                      var module = json[prop][i];

                      if (typeof module === "string")
                      {
                          var fullPath = basePath + "/" + json[prop];

                          var moduleJson = require(fullPath);
                          json[prop][i] = moduleJson;

                          var slash = fullPath.lastIndexOf("/");
                          var rebased = fullPath.substr(0, slash);

                          grunt.option('epubReadingSystem_moduleMap_' + rebased, json[prop][i]);
                          //grunt.config.set(["git-describe", "options", "moduleMap", rebased], json[prop][i]);
                          grunt.task.run('epubReadingSystem_gitDescribe:' + rebased);

                          processModules(rebased, moduleJson);
                      }
                  }
              }
          }
      };

      var epubReadingSystem = grunt.option('epubReadingSystem_JSON');

       processModules(".", epubReadingSystem.readium);
  });

  grunt.registerTask('epubReadingSystem', ['epubReadingSystem_readJSON', 'epubReadingSystem_processModules', 'epubReadingSystem_writeJSON']);
};

<commit_msg>fixed file copy in Grunt build script ("dev" icons)<commit_after>'use strict';

var path = require('path');

module.exports = function (grunt) {

  grunt.initConfig({

   "git-describe": {
      options: {
          cwd: '.'
      },
      target: {
      },
    },

    express: {
      server: {
        options: {
          port: 8080,
          bases: path.resolve(__dirname)
        }
      },
      livereload: true
    },

    requirejs: {
      chromeApp: {
        options: {
          mainConfigFile: './require_config.js',
          include: ['../chrome-app/extended-config','ReadiumViewer'],
          name: 'thirdparty/almond',
          baseUrl: './lib/',
          optimize: 'none',
          out: 'build/chrome-app/scripts/readium-all.js',
          paths: {
            'i18n/Strings': '../chrome-app/i18n/Strings',
            'storage/StorageManager' : '../chrome-app/storage/FileSystemStorage',
            'storage/Settings' : '../chrome-app/storage/ChromeSettings',
            'analytics/Analytics' : '../chrome-app/analytics/ExtensionAnalytics',
            'google-analytics-bundle' : '../chrome-app/analytics/google-analytics-bundle'

          },
          shim: {
            'google-analytics-bundle' : {
              exports: 'analytics'
            }
          }
        }
      },
      chromeAppWorker : {
        options : {
          mainConfigFile: './require_config.js',
          include: ['workers/EpubLibraryWriter'],
          name: 'thirdparty/almond',
          baseUrl: './lib/',
          optimize: 'none',
          out: 'build/chrome-app/scripts/readium-worker.js',
          paths: {
            'i18n/Strings': '../chrome-app/i18n/Strings',
            'storage/StorageManager' : '../chrome-app/storage/FileSystemStorage'
          }
        }
      },
      cloudReader : {
        options: {
          mainConfigFile: './require_config.js',
          include: ['ReadiumViewer'],
          name: 'thirdparty/almond',
          baseUrl: './lib/',
          out: 'build/cloud-reader/scripts/readium-all.js'
        }
      }
    },
    cssmin : {
        chromeApp : {
            files : {
              'build/chrome-app/css/readium-all.css' : ['css/sourcesanspro.css', 'css/bootstrap.css', 'css/readium_js.css', 'css/viewer.css', 'css/library.css']
            }
        },
        cloudReader: {
            files : {
              'build/cloud-reader/css/readium-all.css' : ['css/sourcesanspro.css', 'css/bootstrap.css', 'css/readium_js.css', 'css/viewer.css', 'css/library.css']
            }
        }
    },

    copy : {
      chromeApp: {
        files: [
            {expand: true, cwd: 'chrome-app/', src: ['icons/*.*', 'index.html', 'background.js', 'extended-config.js', 'manifest.json'], dest: 'build/chrome-app'},
            {expand: true, src: 'images/**', dest: 'build/chrome-app'},
            {expand: true, cwd: 'i18n', src: '_locales/**', dest: 'build/chrome-app'},
            {expand: true, cwd: 'lib/thirdparty/', src: ['inflate.js', 'deflate.js'], dest:'build/chrome-app'},
            {expand: true, cwd: 'css', src: 'annotations.css', dest: 'build/chrome-app/css'},
            {expand: true, src: 'fonts/**', dest: 'build/chrome-app'}
        ]
      },
      chromeAppDevBuild: {
        files: [
            {expand: true, cwd: 'chrome-app/icons/devBuild/', src: ['*.*'], dest: 'build/chrome-app/icons/'
            /* , rename: function(dest, src) { return dest + '/' + src } */
            }
        ]
      },
      cloudReader: {
        files: [
          {expand: true, cwd: 'chrome-app/', src: 'index.html', dest: 'build/cloud-reader'},
          {expand: true, src: 'images/**', dest: 'build/cloud-reader'},
          {expand: true, src: 'fonts/**', dest: 'build/cloud-reader'},
          {expand: true, cwd: 'css', src: 'annotations.css', dest: 'build/cloud-reader/css'},
        ]
      },
      cloudReaderEpubContent: {
        files: [
          {expand: true, src: 'epub_content/**/*.*', dest: 'build/cloud-reader'}
        ]
      },
      readiumjs: {
        files: [
          {expand: true, cwd: 'readium-js/out/', src: 'Readium.js', dest: 'lib'}
        ]
      },
      prepareChromeAppTests: {
        files: [
          {expand: true, cwd: 'chrome-app/tests/', src: 'manifest.json', dest: 'build/chrome-app'}
        ]
      }
    },
    nodeunit: {
      chromeApp: ['chrome-app/tests/tests.js']
    },
    clean : {
      chromeApp: ['build/chrome-app'],
      cloudReader: ['build/cloud-reader']
    },
    run_grunt: {
      readiumjs : {
        options: {
          cwd: 'readium-js'
        },
        src: 'readium-js/Gruntfile.js'
      }
    },
    watch : {
      readiumjs:{
        files: ['readium-js/**/*.js','!readium-js/out/Readium.js','!readium-js/**/node_modules/**'],
        tasks: ['update-readium']
      }
    },
    concurrent : {
      serverwatch : {
        tasks: ['runserver', 'watch:readiumjs'],
        options: {
          logConcurrentOutput: true
        }
      }
    }

  });

  grunt.loadNpmTasks('grunt-express');

  grunt.loadNpmTasks('grunt-contrib-requirejs');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-nodeunit');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-run-grunt');
  grunt.loadNpmTasks('grunt-concurrent');

  grunt.loadNpmTasks('grunt-git-describe');

  grunt.registerTask('runserver', ['express', 'express-keepalive']);
  grunt.registerTask('default', 'concurrent:serverwatch');
  grunt.registerTask('update-readium', ['run_grunt:readiumjs', 'copy:readiumjs']);
  grunt.registerTask('test', ['chromeApp', 'copy:prepareChromeAppTests', 'nodeunit:chromeApp']);

  grunt.registerTask('chromeApp', ['clean:chromeApp', 'copy:chromeApp', 'cssmin:chromeApp', 'requirejs:chromeApp', 'requirejs:chromeAppWorker']);

  grunt.registerTask('cloudReader', ['clean:cloudReader', 'copy:cloudReader', 'cssmin:cloudReader', 'requirejs:cloudReader']);
  grunt.registerTask('cloudReaderWithEpub', ['clean:cloudReader', 'copy:cloudReader', 'copy:cloudReaderEpubContent', 'cssmin:cloudReader', 'requirejs:cloudReader']);

  grunt.registerTask('devBuildManifest', function() {
       var manifest = require('./build/chrome-app/manifest.json');

       manifest.description = manifest.description + " (DEV BUILD)";
       manifest.version = manifest.version + ".999";

       var fs = require('fs');
       fs.writeFileSync('./build/chrome-app/manifest.json', JSON.stringify(manifest, null, 2));
  });
  grunt.registerTask('chromeAppDevBuild', [ 'chromeApp', 'copy:chromeAppDevBuild', 'devBuildManifest']);

  //Populates the EPUB3 navigator.epubReadingSystem with versioning information for each Readium component / dependency.
  //This data gets serialised to a JSON file,
  //which should then be pulled by shared_js/readium_sdk.js
  //(because ReadiumSDK creates the app-level navigator.epubReadingSystem object)
  //Normally, the navigator.epubReadingSystem object is "customised" in EpubReader.js (with the correct 'name' and 'version' fields),
  //but this could be done in this build step (i.e. the generated epubReadingSystem.json file is "ready", not need for further customisation)
  //Note that subsequently, the navigator.epubReadingSystem is "forwarded" to each EPUB Content Document's host iframe (see shared_js/iframe_loader.js)
  // Also note that navigator.epubReadingSystem.hasFeature is a Javascript function (taking the parameters "feature" and "version")
  // so it cannot be serialised to JSON (it would just be a string). It therefore has to be defined in a JS file,
  // perhaps shared_js/readium_sdk.js (default baseline), and/or EpubReader.js (customised)

  grunt.registerTask('epubReadingSystem_gitDescribe', function(fullPath) {
grunt.log.writeln("Module directory: " + fullPath);

    var module = grunt.option('epubReadingSystem_moduleMap_' + fullPath);
    //var module = grunt.config.get(["git-describe", "options", "moduleMap", fullPath]);
//grunt.log.writeln("module: " + module);

    //TODO: decide whether to grab info from package.json, or from the computed module info (in which case version comes from Git revision)
    var packageJson = fullPath + '/package.json';
    if (grunt.file.exists(packageJson)) {
        var pack = grunt.file.readJSON(packageJson);
        module.name = pack.name;
        module.version = pack.version;

        if (pack.title || pack.description) {
            module.description = pack.title + " -- " + pack.description;
        }
    }

    grunt.event.once('git-describe', function (rev) {
//grunt.log.writeln("Git Revision: " + rev);

          //grunt.option('gitRevision', rev);
          //var rev = grunt.option('gitRevision');

grunt.log.writeln("Git rev tag: " + rev.tag);
grunt.log.writeln("Git rev since: " + rev.since);
grunt.log.writeln("Git rev object: " + rev.object);
grunt.log.writeln("Git rev dirty: " + rev.dirty);

        module["url_tag"] = module.url + "releases/tag/" + rev.tag;
        module["url_hash"] = module.url + "tree/" + rev.object;

        module.version = rev.tag;
        module.hash = rev.object;

        module.modules = module.modules;
      });

      grunt.config.set(["git-describe", "options", "cwd"], fullPath);
      grunt.task.run('git-describe');
  });

  grunt.registerTask('epubReadingSystem_readJSON', function() {

      //var epubReadingSystem = grunt.file.readJSON('./epubReadingSystem.json');
      var epubReadingSystem = require('./epubReadingSystem.json');

      grunt.option('epubReadingSystem_JSON', epubReadingSystem);
  });

  grunt.registerTask('epubReadingSystem_writeJSON', function() {

      var epubReadingSystem = grunt.option('epubReadingSystem_JSON');

       epubReadingSystem.readium.date = grunt.template.today();

       //TODO: decide whether to grab info from package.json, or from the computed module info (in which case version comes from Git revision)
       var pack = grunt.file.readJSON('package.json');
       epubReadingSystem.name = pack.name;
       epubReadingSystem.version = pack.version;

       epubReadingSystem.name = epubReadingSystem.readium.modules[0].name;
       epubReadingSystem.version = epubReadingSystem.readium.modules[0].version;

       // TODO this gets done in shared_js/readium_sdk.js or EpubReader.js
       //epubReadingSystem.hasFeature = eval(epubReadingSystem.hasFeature);

       var jSon = JSON.stringify(epubReadingSystem, null, 2);
grunt.log.writeln(jSon);

       grunt.file.write('./build/epubReadingSystem.json', jSon);
       // var fs = require('fs');
       // fs.writeFileSync(...);
  });

  grunt.registerTask('epubReadingSystem_processModules', function() {

      Array.isArray = Array.isArray || function (obj) {
          return Object.prototype.toString.call(obj) === "[object Array]";
      };

      var processModules = function(basePath, json)
      {
          for (var prop in json)
          {
              if (!json.hasOwnProperty(prop)) continue;

              if (prop === "modules" && Array.isArray(json[prop]))
              {
                  for (var i = 0; i < json[prop].length; i++)
                  {
                      var module = json[prop][i];

                      if (typeof module === "string")
                      {
                          var fullPath = basePath + "/" + json[prop];

                          var moduleJson = require(fullPath);
                          json[prop][i] = moduleJson;

                          var slash = fullPath.lastIndexOf("/");
                          var rebased = fullPath.substr(0, slash);

                          grunt.option('epubReadingSystem_moduleMap_' + rebased, json[prop][i]);
                          //grunt.config.set(["git-describe", "options", "moduleMap", rebased], json[prop][i]);
                          grunt.task.run('epubReadingSystem_gitDescribe:' + rebased);

                          processModules(rebased, moduleJson);
                      }
                  }
              }
          }
      };

      var epubReadingSystem = grunt.option('epubReadingSystem_JSON');

       processModules(".", epubReadingSystem.readium);
  });

  grunt.registerTask('epubReadingSystem', ['epubReadingSystem_readJSON', 'epubReadingSystem_processModules', 'epubReadingSystem_writeJSON']);
};

<|endoftext|>