<commit_before>import React, {Fragment} from 'react';
import PropTypes from 'prop-types';
import {TextEditor} from 'atom';
import {CompositeDisposable} from 'event-kit';

import RefHolder from '../models/ref-holder';
import {RefHolderPropType} from '../prop-types';
import {autobind, extractProps} from '../helpers';

const editorUpdateProps = {
  mini: PropTypes.bool,
  readOnly: PropTypes.bool,
  placeholderText: PropTypes.string,
  lineNumberGutterVisible: PropTypes.bool,
  autoHeight: PropTypes.bool,
  autoWidth: PropTypes.bool,
  softWrapped: PropTypes.bool,
};

const editorCreationProps = {
  buffer: PropTypes.object, // FIXME make proptype more specific
  ...editorUpdateProps,
};

export const TextEditorContext = React.createContext();

export default class AtomTextEditor extends React.Component {
  static propTypes = {
    ...editorCreationProps,

    workspace: PropTypes.object.isRequired, // FIXME make more specific

    didChangeCursorPosition: PropTypes.func,
    didAddSelection: PropTypes.func,
    didChangeSelectionRange: PropTypes.func,
    didDestroySelection: PropTypes.func,
    observeSelections: PropTypes.func,

    refModel: RefHolderPropType,

    children: PropTypes.node,
  }

  static defaultProps = {
    didChangeCursorPosition: () => {},
    didAddSelection: () => {},
    didChangeSelectionRange: () => {},
    didDestroySelection: () => {},
  }

  constructor(props) {
    super(props);
    autobind(this, 'observeSelections');

    this.subs = new CompositeDisposable();

    this.refParent = new RefHolder();
    this.refElement = new RefHolder();
    this.refModel = null;
  }

  render() {
    return (
      <Fragment>

        <TextEditorContext.Provider value={this.getRefModel()}>
          {this.props.children}
        </TextEditorContext.Provider>
      </Fragment>
    );
  }

  componentDidMount() {
    const modelProps = extractProps(this.props, editorCreationProps);

    this.refParent.map(element => {
      const editor = new TextEditor(modelProps);
      element.appendChild(editor.getElement());
      this.getRefModel().setter(editor);
      this.refElement.setter(editor.getElement());

      this.subs.add(
        editor.onDidChangeCursorPosition(this.props.didChangeCursorPosition),
        editor.observeSelections(this.observeSelections),
      );

      return null;
    });
  }

  componentDidUpdate(prevProps) {
    const modelProps = extractProps(this.props, editorUpdateProps);
    this.getRefModel().map(editor => editor.update(modelProps));
  }

  componentWillUnmount() {
    this.getRefModel().map(editor => editor.destroy());
    this.subs.dispose();
  }

  observeSelections(selection) {
    const selectionSubs = new CompositeDisposable(
      selection.onDidChangeRange(this.props.didChangeSelectionRange),
      selection.onDidDestroy(() => {
        selectionSubs.dispose();
        this.subs.remove(selectionSubs);
        this.props.didDestroySelection(selection);
      }),
    );
    this.subs.add(selectionSubs);
    this.props.didAddSelection(selection);
  }

  contains(element) {
    return this.refElement.map(e => e.contains(element)).getOr(false);
  }

  focus() {
    this.refElement.map(e => e.focus());
  }

  getRefModel() {
    if (this.props.refModel) {
      return this.props.refModel;
    }

    if (!this.refModel) {
      this.refModel = new RefHolder();
    }

    return this.refModel;
  }

  getModel() {
    return this.getRefModel().getOr(undefined);
  }
}
<commit_msg>:fire: an autobind call<commit_after>import React, {Fragment} from 'react';
import PropTypes from 'prop-types';
import {TextEditor} from 'atom';
import {CompositeDisposable} from 'event-kit';

import RefHolder from '../models/ref-holder';
import {RefHolderPropType} from '../prop-types';
import {extractProps} from '../helpers';

const editorUpdateProps = {
  mini: PropTypes.bool,
  readOnly: PropTypes.bool,
  placeholderText: PropTypes.string,
  lineNumberGutterVisible: PropTypes.bool,
  autoHeight: PropTypes.bool,
  autoWidth: PropTypes.bool,
  softWrapped: PropTypes.bool,
};

const editorCreationProps = {
  buffer: PropTypes.object, // FIXME make proptype more specific
  ...editorUpdateProps,
};

export const TextEditorContext = React.createContext();

export default class AtomTextEditor extends React.Component {
  static propTypes = {
    ...editorCreationProps,

    workspace: PropTypes.object.isRequired,

    didChangeCursorPosition: PropTypes.func,
    didAddSelection: PropTypes.func,
    didChangeSelectionRange: PropTypes.func,
    didDestroySelection: PropTypes.func,
    observeSelections: PropTypes.func,

    refModel: RefHolderPropType,

    children: PropTypes.node,
  }

  static defaultProps = {
    didChangeCursorPosition: () => {},
    didAddSelection: () => {},
    didChangeSelectionRange: () => {},
    didDestroySelection: () => {},
  }

  constructor(props) {
    super(props);
    autobind(this, 'observeSelections');

    this.subs = new CompositeDisposable();

    this.refParent = new RefHolder();
    this.refElement = new RefHolder();
    this.refModel = null;
  }

  render() {
    return (
      <Fragment>

        <TextEditorContext.Provider value={this.getRefModel()}>
          {this.props.children}
        </TextEditorContext.Provider>
      </Fragment>
    );
  }

  componentDidMount() {
    const modelProps = extractProps(this.props, editorCreationProps);

    this.refParent.map(element => {
      const editor = new TextEditor(modelProps);
      element.appendChild(editor.getElement());
      this.getRefModel().setter(editor);
      this.refElement.setter(editor.getElement());

      this.subs.add(
        editor.onDidChangeCursorPosition(this.props.didChangeCursorPosition),
        editor.observeSelections(this.observeSelections),
      );

      return null;
    });
  }

  componentDidUpdate(prevProps) {
    const modelProps = extractProps(this.props, editorUpdateProps);
    this.getRefModel().map(editor => editor.update(modelProps));
  }

  componentWillUnmount() {
    this.getRefModel().map(editor => editor.destroy());
    this.subs.dispose();
  }

  observeSelections = selection => {
    const selectionSubs = new CompositeDisposable(
      selection.onDidChangeRange(this.props.didChangeSelectionRange),
      selection.onDidDestroy(() => {
        selectionSubs.dispose();
        this.subs.remove(selectionSubs);
        this.props.didDestroySelection(selection);
      }),
    );
    this.subs.add(selectionSubs);
    this.props.didAddSelection(selection);
  }

  contains(element) {
    return this.refElement.map(e => e.contains(element)).getOr(false);
  }

  focus() {
    this.refElement.map(e => e.focus());
  }

  getRefModel() {
    if (this.props.refModel) {
      return this.props.refModel;
    }

    if (!this.refModel) {
      this.refModel = new RefHolder();
    }

    return this.refModel;
  }

  getModel() {
    return this.getRefModel().getOr(undefined);
  }
}
<|endoftext|>


<commit_before>var Parser = (function(Node, TextNode, Fragment, Component) {

	var interp_START = '~',
		interp_CLOSE = ']',

		// ~
		interp_code_START = 126,
		// [
		interp_code_OPEN = 91,
		// ]
		interp_code_CLOSE = 93,

		_serialize;

	function ensureTemplateFunction(template) {
		var index = -1;

/*
		 * - single char indexOf is much faster then '~[' search
		 * - function is divided in 2 parts: interpolation start lookup/ interpolation parse
		 * for better performance
		 */
		while ((index = template.indexOf(interp_START, index)) !== -1) {
			if (template.charCodeAt(index + 1) === interp_code_OPEN) {
				break;
			}
			index++;
		}

		if (index === -1) {
			return template;
		}

		var array = [],
			lastIndex = 0,
			i = 0,
			end;

		while (true) {
			end = template.indexOf(interp_CLOSE, index + 2);
			if (end === -1) {
				break;
			}

			array[i++] = lastIndex === index ? '' : template.substring(lastIndex, index);
			array[i++] = template.substring(index + 2, end);

			lastIndex = index = end + 1;

			while ((index = template.indexOf(interp_START, index)) !== -1) {
				if (template.charCodeAt(index + 1) === interp_code_OPEN) {
					break;
				}
				index++;
			}

			if (index === -1) {
				break;
			}

		}

		if (lastIndex < template.length) {
			array[i] = template.substring(lastIndex);
		}

		template = null;
		return function(type, model, cntx, element, controller, name) {
			if (type == null) {
				// http://jsperf.com/arguments-length-vs-null-check
				// this should be used to stringify parsed MaskDOM
				var string = '';
				for (var i = 0, x, length = array.length; i < length; i++) {
					x = array[i];
					if (i % 2 === 1) {
						string += '~[' + x + ']';
					} else {
						string += x;
					}
				}
				return string;
			}

			return util_interpolate(array, type, model, cntx, element, controller, name);
		};

	}

	function _throw(template, index, state, token) {
		var parsing = {
				2: 'tag',
				3: 'tag',
				5: 'attribute key',
				6: 'attribute value',
				8: 'literal'
			}[state],

			lines = template.substring(0, index).split('\n'),
			line = lines.length,
			row = lines[line - 1].length,

			message = ['Mask - Unexpected:', token, 'at(', line, ':', row, ') [ in', parsing, ']'];

		console.error(message.join(' '), {
			stopped: template.substring(index),
			template: template
		});
	}

	return {

		/** @out : nodes */
		parse: function(template) {

			//_serialize = T.serialize;

			var current = new Fragment(),
				fragment = current,
				state = 2,
				last = 3,
				index = 0,
				length = template.length,
				classNames, token, key, value, next, c, start;

			var go_tag = 2,
				state_tag = 3,
				state_attr = 5,
				go_attrVal = 6,
				go_attrHeadVal = 7,
				state_literal = 8,
				go_up = 9;

			outer: while (true) {

				if (index < length && (c = template.charCodeAt(index)) < 33) {
					index++;
					continue;
				}

				// inline comments
				if (c === 47 && template.charCodeAt(index + 1) === 47) {
					// /
					index++;
					while (c !== 10 && c !== 13 && index < length) {
						// goto newline
						c = template.charCodeAt(++index);
					}
					continue;
				}

				if (last === state_attr) {
					if (classNames != null) {
						current.attr['class'] = ensureTemplateFunction(classNames);
						classNames = null;
					}
					if (key != null) {
						current.attr[key] = key;
						key = null;
						token = null;
					}
				}

				if (token != null) {

					if (state === state_attr) {

						if (key == null) {
							key = token;
						} else {
							value = token;
						}

						if (key != null && value != null) {
							if (key !== 'class') {
								current.attr[key] = value;
							} else {
								classNames = classNames == null ? value : classNames + ' ' + value;
							}

							key = null;
							value = null;
						}

					} else if (last === state_tag) {

						next = CustomTags[token] != null ? new Component(token, current, CustomTags[token]) : new Node(token, current);

						if (current.nodes == null) {
							current.nodes = [next];
						} else {
							current.nodes.push(next);
						}

						current = next;

						state = state_attr;

					} else if (last === state_literal) {

						next = new TextNode(token, current);

						if (current.nodes == null) {
							current.nodes = [next];
						} else {
							current.nodes.push(next);
						}

						if (current.__single === true) {
							do {
								current = current.parent;
							} while (current != null && current.__single != null);
						}
						state = go_tag;

					}

					token = null;
				}

				if (index >= length) {
					if (state === state_attr) {
						if (classNames != null) {
							current.attr['class'] = ensureTemplateFunction(classNames);
						}
						if (key != null) {
							current.attr[key] = key;
						}
					}

					break;
				}

				if (state === go_up) {
					current = current.parent;
					while (current != null && current.__single != null) {
						current = current.parent;
					}
					state = go_tag;
				}

				// IF statements should be faster then switch due to strict comparison

				if (c === 123) {
					// {

					last = state;
					state = go_tag;
					index++;

					continue;
				}

				if (c === 62) {
					// >
					last = state;
					state = go_tag;
					index++;
					current.__single = true;
					continue;
				}

				if (c === 59) {
					// ;

					// skip ; , when node is not a single tag (else goto 125)
					if (current.nodes != null) {
						index++;
						continue;
					}
				}

				if (c === 59 || c === 125) {
					// ;}

					index++;
					last = state;
					state = go_up;
					continue;
				}

				if (c === 39 || c === 34) {
					// '"
					// Literal - could be as textnode or attribute value
					if (state === go_attrVal) {
						state = state_attr;
					} else {
						last = state = state_literal;
					}

					index++;

					var isEscaped = false,
						nindex, _char = c === 39 ? "'" : '"';

					start = index;

					while ((nindex = template.indexOf(_char, index)) > -1) {
						index = nindex;
						if (template.charCodeAt(nindex - 1) !== 92 /*'\\'*/ ) {
							break;
						}
						isEscaped = true;
						index++;
					}

					token = template.substring(start, index);
					if (isEscaped === true) {
						token = token.replace(regexpEscapedChar[_char], _char);
					}

					token = ensureTemplateFunction(token);

					index++;
					continue;
				}

				if (state === go_tag) {
					last = state_tag;
					state = state_tag;

					if (c === 46 /* . */ || c === 35 /* # */ ) {
						token = 'div';
						continue;
					}
				}

				if (state === state_attr) {
					if (c === 46) {
						// .
						index++;
						key = 'class';
						state = go_attrHeadVal;
					} else if (c === 35) {
						// #
						index++;
						key = 'id';
						state = go_attrHeadVal;
					} else if (c === 61) {
						// =;
						index++;
						state = go_attrVal;
						continue;
					} else {

						if (key != null) {
							token = key;
							continue;
						}
					}
				}

				if (state === go_attrVal || state === go_attrHeadVal) {
					last = state;
					state = state_attr;
				}

				/* TOKEN */

				var isInterpolated = null;

				start = index;
				while (index < length) {

					c = template.charCodeAt(index);

					if (c === interp_code_START && template.charCodeAt(index + 1) === interp_code_OPEN) {
						isInterpolated = true;
						++index;
						do {
							// goto end of template declaration
							c = template.charCodeAt(++index);
						}
						while (c !== interp_code_CLOSE && index < length);
					}

					// if DEBUG
					if (c === 0x0027 || c === 0x0022 || c === 0x002F || c === 0x003C || c === 0x002C) {
						// '"/<,
						_throw(template, index, state, String.fromCharCode(c));
						break;
					}
					// endif

					if (last !== go_attrVal && (c === 46 || c === 35)) {
						// .#
						// break on .# only if parsing attribute head values
						break;
					}

					if (c===61 || c === 62 || c === 123 || c < 33 || c === 59) {
						// =>{ ;
						break;
					}

					index++;
				}

				token = template.substring(start, index);

				// if DEBUG
				if (!token) {
					_throw(template, index, state, '*EMPTY*');
					break;
				}
				if (isInterpolated === true && state === state_tag){
					_throw(template, index, state, 'Tag Names cannt be interpolated (in dev)');
					break;
				}
				// endif

				if (isInterpolated === true && (state === state_attr && key === 'class') === false) {
					token = ensureTemplateFunction(token);
				}

			}

			////if (isNaN(c)) {
			////	_throw(template, index, state, 'Parse IndexOverflow');
			////
			////}

			// if DEBUG
			if (current.parent != null && current.parent !== fragment && current.parent.__single !== true && current.nodes != null) {
				console.warn('Mask - ', current.parent.tagName, JSON.stringify(current.parent.attr), 'was not proper closed.');
			}
			// endif

			return fragment.nodes.length === 1 ? fragment.nodes[0] : fragment;
		},
		cleanObject: function(obj) {
			if (obj instanceof Array) {
				for (var i = 0; i < obj.length; i++) {
					this.cleanObject(obj[i]);
				}
				return obj;
			}
			delete obj.parent;
			delete obj.__single;

			if (obj.nodes != null) {
				this.cleanObject(obj.nodes);
			}

			return obj;
		},
		setInterpolationQuotes: function(start, end) {
			if (!start || start.length !== 2) {
				console.error('Interpolation Start must contain 2 Characters');
				return;
			}
			if (!end || end.length !== 1) {
				console.error('Interpolation End must be of 1 Character');
				return;
			}

			interp_code_START = start.charCodeAt(0);
			interp_code_OPEN = start.charCodeAt(1);
			interp_code_CLOSE = end.charCodeAt(0);
			interp_CLOSE = end;
			interp_START = start.charAt(0);
		}
	};
}(Node, TextNode, Fragment, Component));
<commit_msg>[++] use switch<commit_after>var Parser = (function(Node, TextNode, Fragment, Component) {

	var interp_START = '~',
		interp_CLOSE = ']',

		// ~
		interp_code_START = 126,
		// [
		interp_code_OPEN = 91,
		// ]
		interp_code_CLOSE = 93,

		_serialize;

	function ensureTemplateFunction(template) {
		var index = -1;

		/*
		 * - single char indexOf is much faster then '~[' search
		 * - function is divided in 2 parts: interpolation start lookup/ interpolation parse
		 * for better performance
		 */
		while ((index = template.indexOf(interp_START, index)) !== -1) {
			if (template.charCodeAt(index + 1) === interp_code_OPEN) {
				break;
			}
			index++;
		}

		if (index === -1) {
			return template;
		}

		var array = [],
			lastIndex = 0,
			i = 0,
			end;

		while (true) {
			end = template.indexOf(interp_CLOSE, index + 2);
			if (end === -1) {
				break;
			}

			array[i++] = lastIndex === index ? '' : template.substring(lastIndex, index);
			array[i++] = template.substring(index + 2, end);

			lastIndex = index = end + 1;

			while ((index = template.indexOf(interp_START, index)) !== -1) {
				if (template.charCodeAt(index + 1) === interp_code_OPEN) {
					break;
				}
				index++;
			}

			if (index === -1) {
				break;
			}

		}

		if (lastIndex < template.length) {
			array[i] = template.substring(lastIndex);
		}

		template = null;
		return function(type, model, cntx, element, controller, name) {
			if (type == null) {
				// http://jsperf.com/arguments-length-vs-null-check
				// this should be used to stringify parsed MaskDOM
				var string = '';
				for (var i = 0, x, length = array.length; i < length; i++) {
					x = array[i];
					if (i % 2 === 1) {
						string += '~[' + x + ']';
					} else {
						string += x;
					}
				}
				return string;
			}

			return util_interpolate(array, type, model, cntx, element, controller, name);
		};

	}

	function _throw(template, index, state, token) {
		var parsing = {
				2: 'tag',
				3: 'tag',
				5: 'attribute key',
				6: 'attribute value',
				8: 'literal'
			}[state],

			lines = template.substring(0, index).split('\n'),
			line = lines.length,
			row = lines[line - 1].length,

			message = ['Mask - Unexpected:', token, 'at(', line, ':', row, ') [ in', parsing, ']'];

		console.error(message.join(' '), {
			stopped: template.substring(index),
			template: template
		});
	}

	return {

		/** @out : nodes */
		parse: function(template) {

			//_serialize = T.serialize;

			var current = new Fragment(),
				fragment = current,
				state = 2,
				last = 3,
				index = 0,
				length = template.length,
				classNames, token, key, value, next, c, start;

			var go_tag = 2,
				state_tag = 3,
				state_attr = 5,
				go_attrVal = 6,
				go_attrHeadVal = 7,
				state_literal = 8,
				go_up = 9;

			outer: while (true) {

				if (index < length && (c = template.charCodeAt(index)) < 33) {
					index++;
					continue;
				}

				// inline comments
				if (c === 47 && template.charCodeAt(index + 1) === 47) {
					// /
					index++;
					while (c !== 10 && c !== 13 && index < length) {
						// goto newline
						c = template.charCodeAt(++index);
					}
					continue;
				}

				if (last === state_attr) {
					if (classNames != null) {
						current.attr['class'] = ensureTemplateFunction(classNames);
						classNames = null;
					}
					if (key != null) {
						current.attr[key] = key;
						key = null;
						token = null;
					}
				}

				if (token != null) {

					if (state === state_attr) {

						if (key == null) {
							key = token;
						} else {
							value = token;
						}

						if (key != null && value != null) {
							if (key !== 'class') {
								current.attr[key] = value;
							} else {
								classNames = classNames == null ? value : classNames + ' ' + value;
							}

							key = null;
							value = null;
						}

					} else if (last === state_tag) {

						next = CustomTags[token] != null ? new Component(token, current, CustomTags[token]) : new Node(token, current);

						if (current.nodes == null) {
							current.nodes = [next];
						} else {
							current.nodes.push(next);
						}

						current = next;

						state = state_attr;

					} else if (last === state_literal) {

						next = new TextNode(token, current);

						if (current.nodes == null) {
							current.nodes = [next];
						} else {
							current.nodes.push(next);
						}

						if (current.__single === true) {
							do {
								current = current.parent;
							} while (current != null && current.__single != null);
						}
						state = go_tag;

					}

					token = null;
				}

				if (index >= length) {
					if (state === state_attr) {
						if (classNames != null) {
							current.attr['class'] = ensureTemplateFunction(classNames);
						}
						if (key != null) {
							current.attr[key] = key;
						}
					}

					break;
				}

				if (state === go_up) {
					current = current.parent;
					while (current != null && current.__single != null) {
						current = current.parent;
					}
					state = go_tag;
				}

				switch (c) {
				case 123:
					// {

					last = state;
					state = go_tag;
					index++;

					continue;
				case 62:
					// >
					last = state;
					state = go_tag;
					index++;
					current.__single = true;
					continue;

				case 59:
					// ;

					// skip ; , when node is not a single tag (else goto 125)
					if (current.nodes != null) {
						index++;
						continue;
					}

					/* falls through */
				case 125:
					// ;}

					index++;
					last = state;
					state = go_up;
					continue;

				case 39:
				case 34:
					// '"
					// Literal - could be as textnode or attribute value
					if (state === go_attrVal) {
						state = state_attr;
					} else {
						last = state = state_literal;
					}

					index++;

					var isEscaped = false,
						nindex, _char = c === 39 ? "'" : '"';

					start = index;

					while ((nindex = template.indexOf(_char, index)) > -1) {
						index = nindex;
						if (template.charCodeAt(nindex - 1) !== 92 /*'\\'*/ ) {
							break;
						}
						isEscaped = true;
						index++;
					}

					token = template.substring(start, index);
					if (isEscaped === true) {
						token = token.replace(regexpEscapedChar[_char], _char);
					}

					token = ensureTemplateFunction(token);

					index++;
					continue;
				}

				if (state === go_tag) {
					last = state_tag;
					state = state_tag;

					if (c === 46 /* . */ || c === 35 /* # */ ) {
						token = 'div';
						continue;
					}
				}

				else if (state === state_attr) {
					if (c === 46) {
						// .
						index++;
						key = 'class';
						state = go_attrHeadVal;
					} else if (c === 35) {
						// #
						index++;
						key = 'id';
						state = go_attrHeadVal;
					} else if (c === 61) {
						// =;
						index++;
						state = go_attrVal;
						continue;
					} else {

						if (key != null) {
							token = key;
							continue;
						}
					}
				}

				if (state === go_attrVal || state === go_attrHeadVal) {
					last = state;
					state = state_attr;
				}

				/* TOKEN */

				var isInterpolated = null;

				start = index;
				while (index < length) {

					c = template.charCodeAt(index);

					if (c === interp_code_START && template.charCodeAt(index + 1) === interp_code_OPEN) {
						isInterpolated = true;
						++index;
						do {
							// goto end of template declaration
							c = template.charCodeAt(++index);
						}
						while (c !== interp_code_CLOSE && index < length);
					}

					// if DEBUG
					if (c === 0x0027 || c === 0x0022 || c === 0x002F || c === 0x003C || c === 0x002C) {
						// '"/<,
						_throw(template, index, state, String.fromCharCode(c));
						break;
					}
					// endif

					if (last !== go_attrVal && (c === 46 || c === 35)) {
						// .#
						// break on .# only if parsing attribute head values
						break;
					}

					if (c === 61 || c === 62 || c === 123 || c < 33 || c === 59) {
						// =>{ ;
						break;
					}

					index++;
				}

				token = template.substring(start, index);

				// if DEBUG
				if (!token) {
					_throw(template, index, state, '*EMPTY*');
					break;
				}
				if (isInterpolated === true && state === state_tag) {
					_throw(template, index, state, 'Tag Names cannt be interpolated (in dev)');
					break;
				}
				// endif

				if (isInterpolated === true && (state === state_attr && key === 'class') === false) {
					token = ensureTemplateFunction(token);
				}

			}

			////if (isNaN(c)) {
			////	_throw(template, index, state, 'Parse IndexOverflow');
			////
			////}

			// if DEBUG
			if (current.parent != null && current.parent !== fragment && current.parent.__single !== true && current.nodes != null) {
				console.warn('Mask - ', current.parent.tagName, JSON.stringify(current.parent.attr), 'was not proper closed.');
			}
			// endif

			return fragment.nodes.length === 1 ? fragment.nodes[0] : fragment;
		},
		cleanObject: function(obj) {
			if (obj instanceof Array) {
				for (var i = 0; i < obj.length; i++) {
					this.cleanObject(obj[i]);
				}
				return obj;
			}
			delete obj.parent;
			delete obj.__single;

			if (obj.nodes != null) {
				this.cleanObject(obj.nodes);
			}

			return obj;
		},
		setInterpolationQuotes: function(start, end) {
			if (!start || start.length !== 2) {
				console.error('Interpolation Start must contain 2 Characters');
				return;
			}
			if (!end || end.length !== 1) {
				console.error('Interpolation End must be of 1 Character');
				return;
			}

			interp_code_START = start.charCodeAt(0);
			interp_code_OPEN = start.charCodeAt(1);
			interp_code_CLOSE = end.charCodeAt(0);
			interp_CLOSE = end;
			interp_START = start.charAt(0);
		}
	};
}(Node, TextNode, Fragment, Component));
<|endoftext|>


<commit_before>var express = require('express');
var exphbs  = require('express-handlebars');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var path = require('path');
var assert = require('assert');
var env = require('node-env-file');

var index = require('./routes/index');
var api = require('./routes/api');

var app = express();
var hbs = exphbs.create({ defaultLayout: 'default' });

env(__dirname + '/.env');

app.use(function (req, res, next) {

    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', '*');

    // Request methods you wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

    // Request headers you wish to allow
    res.setHeader('Access-Control-Allow-Headers', '*');

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader('Access-Control-Allow-Credentials', true);

    // Pass to next layer of middleware
    next();
});

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');

// uncomment when deploying to production for view caching
// app.enable('view cache');

// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger(process.env.NODE_ENV));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);
app.use('/api', api);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

module.exports = app;
<commit_msg>Removed extra require(path)<commit_after>var express = require('express');
var exphbs  = require('express-handlebars');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var assert = require('assert');
var env = require('node-env-file');

var index = require('./routes/index');
var api = require('./routes/api');

var app = express();
var hbs = exphbs.create({ defaultLayout: 'default' });

env(__dirname + '/.env');

app.use(function (req, res, next) {

    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', '*');

    // Request methods you wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

    // Request headers you wish to allow
    res.setHeader('Access-Control-Allow-Headers', '*');

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader('Access-Control-Allow-Credentials', true);

    // Pass to next layer of middleware
    next();
});

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');

// uncomment when deploying to production for view caching
// app.enable('view cache');

// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger(process.env.NODE_ENV));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);
app.use('/api', api);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

module.exports = app;
<|endoftext|>


<commit_before>this.data = document.body.innerHTML;
this.uri = document.location.href;

if(document.getElementsByTagName("pre")[0]){
  // console.log("JSONView: data is wrapped in
...
, stripping HTML...");
  this.data = document.getElementsByTagName("pre")[0].innerHTML;
}

function IsJsonString(str) {
  try {
      JSON.parse(str);
  } catch (e) {
      return false;
  }
  return true;
}

var is_json = IsJsonString(this.data);

if(is_json){
  if (!(window.location.hash === "#raw-json")){
    /*
     * The JSONFormatter helper object. This contains two major functions, jsonToHTML and errorPage,
     * each of which returns an HTML document.
     */
    function JSONFormatter() { }

    JSONFormatter.prototype = {
      /**
       * Completely escape a json string
       */
      jsString: function(s) {
        // Slice off the surrounding quotes
        s = JSON.stringify(s).slice(1, -1);
        return s;
      },

      /**
       * Is this a valid "bare" property name?
       */
      isBareProp: function(prop) {
        return /^[A-Za-z_$][A-Za-z0-9_\-$]*$/.test(prop);
      },

      /**
       * Surround value with a span, including the given className
       */
      decorateWithSpan: function(value, className) {
        return '' + value + '';
      },

      // Convert a basic JSON datatype (number, string, boolean, null, object, array) into an HTML fragment.
      valueToHTML: function(value, path) {
        var valueType = typeof value;

        if (value === null) {
          return this.decorateWithSpan('null', 'null');
        }
        else if (Array.isArray(value)) {
          return this.arrayToHTML(value, path);
        }
        else if (valueType == 'object') {
          return this.objectToHTML(value, path);
        }
        else if (valueType == 'number') {
          return this.decorateWithSpan(value, 'num');
        }
        else if (valueType == 'string') {
          if (/^(http|https|file):\/\/[^\s]+$/i.test(value)) {
            return '"' + this.jsString(value) + '"';
          } else {
            return '"' + this.jsString(value) + '"';
          }
        }
        else if (valueType == 'boolean') {
          return this.decorateWithSpan(value, 'bool');
        }

        return '';
      },

      // Convert an array into an HTML fragment
      arrayToHTML: function(json, path) {
        if (json.length === 0) {
          return '[ ]';
        }

        var output = '';
        for (var i = 0; i < json.length; i++) {
          var subPath = path + '[' + i + ']';
          output += '
' + this.valueToHTML(json[i], subPath);
          if (i < json.length - 1) {
            output += ',';
          }
          output += '
';
        }
        return '[
' + output + '
]';
      },

      // Convert a JSON object to an HTML fragment
      objectToHTML: function(json, path) {
        var numProps = Object.keys(json).length;
        if (numProps === 0) {
          return '{ }';
        }

        var output = '';
        for (var prop in json) {
          var subPath = '';
          var escapedProp = JSON.stringify(prop).slice(1, -1);
          var bare = this.isBareProp(prop);
          if (bare) {
            subPath = path + '.' + escapedProp;
          } else {
            escapedProp = '"' + escapedProp + '"';
          }
          output += '
"' + this.jsString(prop) +
            '": ' + this.valueToHTML(json[prop], subPath);
          if (numProps > 1) {
            output += ',';
          }
          output += '
';
          numProps--;
        }

        return '{
' + output + '
}';
      },

      // Convert a whole JSON value / JSONP response into a formatted HTML document
      jsonToHTML: function(json, callback, uri) {
        var output = '
' + this.valueToHTML(json, '<root>') + '
';
        if (callback) {
          output = '
' + callback + '(
' + output + '
)
';
        }
        return this.toHTML(output, uri);
      },

      // Clean up a JSON parsing error message
      massageError: function(error) {
        var message = error.message.replace(/^JSON.parse: /, '').replace(/of the JSON data/, '');
        var parts = /line (\d+) column (\d+)/.exec(message);

        return {
          message: message,
          line: +parts[1],
          column: +parts[2]
        };
      },

      highlightError: function(data, lineNum, columnNum) {
        if (!lineNum || !columnNum) {
          return data;
        }

        var lines = data.match(/^.*((\r\n|\n|\r)|$)/gm);

        var output = '';
        for (var i = 0; i < lines.length; i++) {
          var line = lines[i];

          if (i == lineNum - 1) {
            output += '';
            output += line.substring(0, columnNum - 1) + '' + line[columnNum - 1] + '' + line.substring(columnNum);
            output += '';
          } else {
            output += line;
          }
        }

        return output;
      },

      // Produce an error document for when parsing fails.
      errorPage: function(error, data, uri) {
        // Escape unicode nulls
        data = data.replace("\u0000","\uFFFD");

        var errorInfo = this.massageError(error);

        var output = '
' + _('errorParsing');
        if (errorInfo.message) {
          output += '
' + errorInfo.message + '
';
        }
        output += '

' + this.highlightError(data, errorInfo.line, errorInfo.column) + '
';
        return this.toHTML(output, uri + ' - Error');
      },

      // Wrap the HTML fragment in a full document. Used by jsonToHTML and errorPage.
      toHTML: function(content, title) {
        return '<!DOCTYPE html>\n' +
          '<meta charset="UTF-8"><title>' + title + '</title>' +
          '<link rel="stylesheet" type="text/css" href="' + safari.extension.baseURI + "default.css" + '">' +
          '' +
          content +
          '';
      }
    };

    // Sanitize & output -- all magic from JSONView Firefox
    this.jsonFormatter = new JSONFormatter();

    // This regex attempts to match a JSONP structure:
    //    * Any amount of whitespace (including unicode nonbreaking spaces) between the start of the file and the callback name
    //    * Callback name (any valid JavaScript function name according to ECMA-262 Edition 3 spec)
    //    * Any amount of whitespace (including unicode nonbreaking spaces)
    //    * Open parentheses
    //    * Any amount of whitespace (including unicode nonbreaking spaces)
    //    * Either { or [, the only two valid characters to start a JSON string.
    //    * Any character, any number of times
    //    * Either } or ], the only two valid closing characters of a JSON string.
    //    * Any amount of whitespace (including unicode nonbreaking spaces)
    //    * A closing parenthesis, an optional semicolon, and any amount of whitespace (including unicode nonbreaking spaces) until the end of the file.
    // This will miss anything that has comments, or more than one callback, or requires modification before use.
    var outputDoc = '';
    // text = text.match(jsonp_regex)[1];
    var cleanData = '',
        callback = '';

    var callback_results = IsJsonString(this.data);
    if( callback_results && callback_results.length == 3 ){
      // console.log("THIS IS JSONp");
      callback = callback_results[1];
      cleanData = callback_results[2];
    } else {
      // console.log("Vanilla JSON");
      cleanData = this.data;
    }
    // console.log(cleanData);

    // Covert, and catch exceptions on failure
    try {
      // var jsonObj = this.nativeJSON.decode(cleanData);
      var jsonObj = JSON.parse(cleanData);
      if ( jsonObj ) {
        outputDoc = this.jsonFormatter.jsonToHTML(jsonObj, callback, this.uri);
      } else {
        throw "There was no object!";
      }
    } catch(e) {
      // console.log(e);
      outputDoc = this.jsonFormatter.errorPage(e, this.data, this.uri);
    }
    // document.body.innerHTML = outputDoc;
    document.documentElement.innerHTML = 'RAW' + outputDoc;

    //////////////////////////////////
    ////////BEGINS DEFAULT.JS/////////
    //////////////////////////////////

    // Click handler for collapsing and expanding objects and arrays
    function collapse(evt) {
      var collapser = evt.target;

      while (collapser && (!collapser.classList || !collapser.classList.contains('collapser'))) {
        collapser = collapser.nextSibling;
      }
      if (!collapser || !collapser.classList || !collapser.classList.contains('collapser')) {
        return;
      }

      evt.stopPropagation();

      collapser.classList.toggle('collapsed');

      var collapsible = collapser;
      while (collapsible && (!collapsible.classList || !collapsible.classList.contains('collapsible'))) {
        collapsible = collapsible.nextSibling;
      }
      collapsible.classList.toggle('collapsed');
    }

    /*
     * Collapses the whole json using keyboard
     * TODO: Add a navigator support for each of the elements
     */
    function collapseAll(evt) {
      var inputList;

      // Ignore anything paired with a modifier key. See https://github.com/bhollis/jsonview/issues/69
      if (evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) {
        return;
      }

      if (evt.keyCode === 37) {  // Collapses the json on left arrow key up
        inputList = document.querySelectorAll('.collapsible, .collapser');
        for (var i = 0; i < inputList.length; i++) {
          if (inputList[i].parentNode.id != 'json') {
            inputList[i].classList.add('collapsed');
          }
        }
        evt.preventDefault();
      } else if (evt.keyCode === 39) { // Expands the json on right arrow key up
        inputList = document.querySelectorAll('.collapsed');
        for (var i = 0; i < inputList.length; i++) {
          inputList[i].classList.remove('collapsed');
        }
        evt.preventDefault();
      }
    }

    // collapse with event delegation
    document.addEventListener('click', collapse, false);
    document.addEventListener('keyup', collapseAll, false);

    //////////////////////////////////
    /////////ENDS DEFAULT.JS//////////
    //////////////////////////////////

    /**
    * Converts the markup to DOM nodes
    *
    * @private
    * @param {string|Markup} value The node
    * @return {Node}
    */
    function toDOM(value) {
      var wrapper = createElement('div');
      wrapper.innerHTML = ''+value;

      // trim extraneous whitespace
      trimWhitespace(wrapper);

      // eliminate wrapper for single nodes
      if (wrapper.childNodes.length === 1) {
        return wrapper.firstChild;
      }

      // create a document fragment to hold elements
      var frag = createElement('');
      while (wrapper.firstChild) {
        frag.appendChild(wrapper.firstChild);
      }
      return frag;
    }
    var rawButton = document.getElementById('raw');
    rawButton.href = location.protocol+'//'+location.host+location.pathname+'?&jsonace='+Math.floor(Math.random()*1000)+'#raw-json';
  } else {
    var outputDoc = 'BEAUTIFY' + this.data;
    var impcss = document.createElement('link');
    impcss.rel = "stylesheet";
    impcss.href = safari.extension.baseURI + 'default.css';
    document.head.appendChild(impcss);
    document.body.innerHTML = outputDoc;
  }
}else {
  // console.log("JSONView: this is not json, not formatting.");
}
<commit_msg>parse pre only if 1 exists<commit_after>this.data = document.body.innerHTML;
this.uri = document.location.href;

if(document.getElementsByTagName("pre")[0] && document.getElementsByTagName("pre").length == 1){
  // console.log("JSONView: data is wrapped in
...
, stripping HTML...");
  this.data = document.getElementsByTagName("pre")[0].innerHTML;
}

function IsJsonString(str) {
  try {
      JSON.parse(str);
  } catch (e) {
      return false;
  }
  return true;
}

var is_json = IsJsonString(this.data);

if(is_json){
  if (!(window.location.hash === "#raw-json")){
    /*
     * The JSONFormatter helper object. This contains two major functions, jsonToHTML and errorPage,
     * each of which returns an HTML document.
     */
    function JSONFormatter() { }

    JSONFormatter.prototype = {
      /**
       * Completely escape a json string
       */
      jsString: function(s) {
        // Slice off the surrounding quotes
        s = JSON.stringify(s).slice(1, -1);
        return s;
      },

      /**
       * Is this a valid "bare" property name?
       */
      isBareProp: function(prop) {
        return /^[A-Za-z_$][A-Za-z0-9_\-$]*$/.test(prop);
      },

      /**
       * Surround value with a span, including the given className
       */
      decorateWithSpan: function(value, className) {
        return '' + value + '';
      },

      // Convert a basic JSON datatype (number, string, boolean, null, object, array) into an HTML fragment.
      valueToHTML: function(value, path) {
        var valueType = typeof value;

        if (value === null) {
          return this.decorateWithSpan('null', 'null');
        }
        else if (Array.isArray(value)) {
          return this.arrayToHTML(value, path);
        }
        else if (valueType == 'object') {
          return this.objectToHTML(value, path);
        }
        else if (valueType == 'number') {
          return this.decorateWithSpan(value, 'num');
        }
        else if (valueType == 'string') {
          if (/^(http|https|file):\/\/[^\s]+$/i.test(value)) {
            return '"' + this.jsString(value) + '"';
          } else {
            return '"' + this.jsString(value) + '"';
          }
        }
        else if (valueType == 'boolean') {
          return this.decorateWithSpan(value, 'bool');
        }

        return '';
      },

      // Convert an array into an HTML fragment
      arrayToHTML: function(json, path) {
        if (json.length === 0) {
          return '[ ]';
        }

        var output = '';
        for (var i = 0; i < json.length; i++) {
          var subPath = path + '[' + i + ']';
          output += '
' + this.valueToHTML(json[i], subPath);
          if (i < json.length - 1) {
            output += ',';
          }
          output += '
';
        }
        return '[
' + output + '
]';
      },

      // Convert a JSON object to an HTML fragment
      objectToHTML: function(json, path) {
        var numProps = Object.keys(json).length;
        if (numProps === 0) {
          return '{ }';
        }

        var output = '';
        for (var prop in json) {
          var subPath = '';
          var escapedProp = JSON.stringify(prop).slice(1, -1);
          var bare = this.isBareProp(prop);
          if (bare) {
            subPath = path + '.' + escapedProp;
          } else {
            escapedProp = '"' + escapedProp + '"';
          }
          output += '
"' + this.jsString(prop) +
            '": ' + this.valueToHTML(json[prop], subPath);
          if (numProps > 1) {
            output += ',';
          }
          output += '
';
          numProps--;
        }

        return '{
' + output + '
}';
      },

      // Convert a whole JSON value / JSONP response into a formatted HTML document
      jsonToHTML: function(json, callback, uri) {
        var output = '
' + this.valueToHTML(json, '<root>') + '
';
        if (callback) {
          output = '
' + callback + '(
' + output + '
)
';
        }
        return this.toHTML(output, uri);
      },

      // Clean up a JSON parsing error message
      massageError: function(error) {
        var message = error.message.replace(/^JSON.parse: /, '').replace(/of the JSON data/, '');
        var parts = /line (\d+) column (\d+)/.exec(message);

        return {
          message: message,
          line: +parts[1],
          column: +parts[2]
        };
      },

      highlightError: function(data, lineNum, columnNum) {
        if (!lineNum || !columnNum) {
          return data;
        }

        var lines = data.match(/^.*((\r\n|\n|\r)|$)/gm);

        var output = '';
        for (var i = 0; i < lines.length; i++) {
          var line = lines[i];

          if (i == lineNum - 1) {
            output += '';
            output += line.substring(0, columnNum - 1) + '' + line[columnNum - 1] + '' + line.substring(columnNum);
            output += '';
          } else {
            output += line;
          }
        }

        return output;
      },

      // Produce an error document for when parsing fails.
      errorPage: function(error, data, uri) {
        // Escape unicode nulls
        data = data.replace("\u0000","\uFFFD");

        var errorInfo = this.massageError(error);

        var output = '
' + _('errorParsing');
        if (errorInfo.message) {
          output += '
' + errorInfo.message + '
';
        }
        output += '

' + this.highlightError(data, errorInfo.line, errorInfo.column) + '
';
        return this.toHTML(output, uri + ' - Error');
      },

      // Wrap the HTML fragment in a full document. Used by jsonToHTML and errorPage.
      toHTML: function(content, title) {
        return '<!DOCTYPE html>\n' +
          '<meta charset="UTF-8"><title>' + title + '</title>' +
          '<link rel="stylesheet" type="text/css" href="' + safari.extension.baseURI + "default.css" + '">' +
          '' +
          content +
          '';
      }
    };

    // Sanitize & output -- all magic from JSONView Firefox
    this.jsonFormatter = new JSONFormatter();

    // This regex attempts to match a JSONP structure:
    //    * Any amount of whitespace (including unicode nonbreaking spaces) between the start of the file and the callback name
    //    * Callback name (any valid JavaScript function name according to ECMA-262 Edition 3 spec)
    //    * Any amount of whitespace (including unicode nonbreaking spaces)
    //    * Open parentheses
    //    * Any amount of whitespace (including unicode nonbreaking spaces)
    //    * Either { or [, the only two valid characters to start a JSON string.
    //    * Any character, any number of times
    //    * Either } or ], the only two valid closing characters of a JSON string.
    //    * Any amount of whitespace (including unicode nonbreaking spaces)
    //    * A closing parenthesis, an optional semicolon, and any amount of whitespace (including unicode nonbreaking spaces) until the end of the file.
    // This will miss anything that has comments, or more than one callback, or requires modification before use.
    var outputDoc = '';
    // text = text.match(jsonp_regex)[1];
    var cleanData = '',
        callback = '';

    var callback_results = IsJsonString(this.data);
    if( callback_results && callback_results.length == 3 ){
      // console.log("THIS IS JSONp");
      callback = callback_results[1];
      cleanData = callback_results[2];
    } else {
      // console.log("Vanilla JSON");
      cleanData = this.data;
    }
    // console.log(cleanData);

    // Covert, and catch exceptions on failure
    try {
      // var jsonObj = this.nativeJSON.decode(cleanData);
      var jsonObj = JSON.parse(cleanData);
      if ( jsonObj ) {
        outputDoc = this.jsonFormatter.jsonToHTML(jsonObj, callback, this.uri);
      } else {
        throw "There was no object!";
      }
    } catch(e) {
      // console.log(e);
      outputDoc = this.jsonFormatter.errorPage(e, this.data, this.uri);
    }
    // document.body.innerHTML = outputDoc;
    document.documentElement.innerHTML = 'RAW' + outputDoc;

    //////////////////////////////////
    ////////BEGINS DEFAULT.JS/////////
    //////////////////////////////////

    // Click handler for collapsing and expanding objects and arrays
    function collapse(evt) {
      var collapser = evt.target;

      while (collapser && (!collapser.classList || !collapser.classList.contains('collapser'))) {
        collapser = collapser.nextSibling;
      }
      if (!collapser || !collapser.classList || !collapser.classList.contains('collapser')) {
        return;
      }

      evt.stopPropagation();

      collapser.classList.toggle('collapsed');

      var collapsible = collapser;
      while (collapsible && (!collapsible.classList || !collapsible.classList.contains('collapsible'))) {
        collapsible = collapsible.nextSibling;
      }
      collapsible.classList.toggle('collapsed');
    }

    /*
     * Collapses the whole json using keyboard
     * TODO: Add a navigator support for each of the elements
     */
    function collapseAll(evt) {
      var inputList;

      // Ignore anything paired with a modifier key. See https://github.com/bhollis/jsonview/issues/69
      if (evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) {
        return;
      }

      if (evt.keyCode === 37) {  // Collapses the json on left arrow key up
        inputList = document.querySelectorAll('.collapsible, .collapser');
        for (var i = 0; i < inputList.length; i++) {
          if (inputList[i].parentNode.id != 'json') {
            inputList[i].classList.add('collapsed');
          }
        }
        evt.preventDefault();
      } else if (evt.keyCode === 39) { // Expands the json on right arrow key up
        inputList = document.querySelectorAll('.collapsed');
        for (var i = 0; i < inputList.length; i++) {
          inputList[i].classList.remove('collapsed');
        }
        evt.preventDefault();
      }
    }

    // collapse with event delegation
    document.addEventListener('click', collapse, false);
    document.addEventListener('keyup', collapseAll, false);

    //////////////////////////////////
    /////////ENDS DEFAULT.JS//////////
    //////////////////////////////////

    /**
    * Converts the markup to DOM nodes
    *
    * @private
    * @param {string|Markup} value The node
    * @return {Node}
    */
    function toDOM(value) {
      var wrapper = createElement('div');
      wrapper.innerHTML = ''+value;

      // trim extraneous whitespace
      trimWhitespace(wrapper);

      // eliminate wrapper for single nodes
      if (wrapper.childNodes.length === 1) {
        return wrapper.firstChild;
      }

      // create a document fragment to hold elements
      var frag = createElement('');
      while (wrapper.firstChild) {
        frag.appendChild(wrapper.firstChild);
      }
      return frag;
    }
    var rawButton = document.getElementById('raw');
    rawButton.href = location.protocol+'//'+location.host+location.pathname+'?&jsonace='+Math.floor(Math.random()*1000)+'#raw-json';
  } else {
    var outputDoc = 'BEAUTIFY' + this.data;
    var impcss = document.createElement('link');
    impcss.rel = "stylesheet";
    impcss.href = safari.extension.baseURI + 'default.css';
    document.head.appendChild(impcss);
    document.body.innerHTML = outputDoc;
  }
}else {
  // console.log("JSONView: this is not json, not formatting.");
}
<|endoftext|>


<commit_before>import path from 'path'
import rimraf from 'rimraf'
import webpack from 'webpack'
import config from '../config'
import isomorphicWebpackConfig from '../webpack.isomorphic'
import AssetsPlugin from 'assets-webpack-plugin'
import FaviconsWebpackPlugin from 'favicons-webpack-plugin'
import WebpackAssetsManifest from 'webpack-assets-manifest'
const {
	GA_ID,
	SENTRY_PUBLIC_DSN,
	CLIENT_DIST_PATH,
	rootPath,
	srcPath,
	publicPath,
	isProduction,
	title,
	manifest
} = config

rimraf(`${config.distPath}/server`, {}, () => {})

const definePluginArgs = {
	'process.env.GA_ID': JSON.stringify(GA_ID),
	'process.env.SENTRY_PUBLIC_DSN': JSON.stringify(SENTRY_PUBLIC_DSN),
	'process.env.BROWSER': JSON.stringify(true)
}

// use hash filename to support long-term caching in production
const filename = isProduction ? '[name].[chunkhash:8].js' : '[name].js'
const hints = isProduction ? 'warning' : false
const devtool = isProduction ? 'cheap-source-map' : 'eval'

const baseBuild = {
	name: 'client',
	devtool,
	entry: {
		client: path.join(srcPath, './client')
	},
	output: {
		filename,
		publicPath,
		path: CLIENT_DIST_PATH,
		chunkFilename: '[name].[chunkhash:6].js',
		crossOriginLoading: 'anonymous'
	},
	performance: {
		hints
	},
	resolve: {
		alias: {
			...isomorphicWebpackConfig.resolve.alias
			// NOTE: Preact + preact-compat can save you 148Kb parsed or 14kb gzipped
			// Preact may breaks your React app, starter by default doesn't aim to support Preact
			// react: 'preact-compat',
			// 'react-dom': 'preact-compat',
			// 'preact-compat': 'preact-compat/dist/preact-compat'
		},
		modules: isomorphicWebpackConfig.resolve.modules,
		extensions: isomorphicWebpackConfig.resolve.extensions.concat([
			'.css',
			'.scss',
			'.sass'
		])
	},
	module: {
		rules: isomorphicWebpackConfig.module.rules.concat([
			{
				test: /\.(ico|eot|otf|webp|ttf|woff|woff2)$/i,
				use: `file-loader?limit=100000&name=assets/[name].[hash:8].[ext]`
			},
			{
				test: /\.(jpe?g|png|gif|svg)$/,
				use: [
					{
						loader: 'url-loader',
						options: {
							limit: 4096,
							// path: '/images',
							name: 'images/[name].[hash:8].[ext]'
						}
					},
					'img-loader'
				]
			}
			// NOTE: LQIP loader doesn't work with file-loader and url-loader :(
			// `npm i --save-dev lqip-loader`
			// {
			//   test: /\.(jpe?g|png)$/i,
			//   enforce: 'pre',
			//   loaders: [
			//     {
			//       loader: 'lqip-loader',
			//       options: {
			//         path: '/images-lqip', // your image going to be in media folder in the output dir
			//         name: '[name]-lqip.[hash:8].[ext]' // you can use [hash].[ext] too if you wish
			//       }
			//     }
			//   ]
			// }
		])
	},
	plugins: isomorphicWebpackConfig.plugins.concat([
		new webpack.DefinePlugin(definePluginArgs),
		new AssetsPlugin({
			path: CLIENT_DIST_PATH
		}),
		// NOTE: this plugin is good, but there are few big issues:
		// 1. It sets invalid url to browserconfig.xml and manifest.json in index.html.
		// E.g: in generated index.html you can see:
		// <meta name="msapplication-config" content="browserconfig.xml">
		// 2. It looks like generated images aren't minified.(not sure)
		// NOTE: It would be better to generate favicons without this plugin.
		new FaviconsWebpackPlugin({
			// add theme-color property
			background: manifest.theme,
			prefix: `favicons/`,
			logo: path.join(rootPath, './static/images/Logo.png'),
			title,
			emitStats: true,
			statsFilename: 'favicons-stats.json',
			// Inject generated html into html-webpack-plugin
			inject: false,
			// which icons should be generated (see https://github.com/haydenbleasel/favicons#usage)
			icons: {
				android: false,
				appleIcon: true,
				appleStartup: true,
				coast: false,
				favicons: true,
				firefox: true,
				opengraph: false,
				twitter: true,
				yandex: false,
				windows: false
			}
		}),
		new WebpackAssetsManifest({
			assets: config.manifest
		})
	]),
	target: 'web'
}

export default baseBuild
<commit_msg>chore(webpack_config): generate less favicons<commit_after>import path from 'path'
import rimraf from 'rimraf'
import webpack from 'webpack'
import config from '../config'
import isomorphicWebpackConfig from '../webpack.isomorphic'
import AssetsPlugin from 'assets-webpack-plugin'
import FaviconsWebpackPlugin from 'favicons-webpack-plugin'
import WebpackAssetsManifest from 'webpack-assets-manifest'
const {
	GA_ID,
	SENTRY_PUBLIC_DSN,
	CLIENT_DIST_PATH,
	rootPath,
	srcPath,
	publicPath,
	isProduction,
	title,
	manifest
} = config

rimraf(`${config.distPath}/server`, {}, () => {})

const definePluginArgs = {
	'process.env.GA_ID': JSON.stringify(GA_ID),
	'process.env.SENTRY_PUBLIC_DSN': JSON.stringify(SENTRY_PUBLIC_DSN),
	'process.env.BROWSER': JSON.stringify(true)
}

// use hash filename to support long-term caching in production
const filename = isProduction ? '[name].[chunkhash:8].js' : '[name].js'
const hints = isProduction ? 'warning' : false
const devtool = isProduction ? 'cheap-source-map' : 'eval'

const baseBuild = {
	name: 'client',
	devtool,
	entry: {
		client: path.join(srcPath, './client')
	},
	output: {
		filename,
		publicPath,
		path: CLIENT_DIST_PATH,
		chunkFilename: '[name].[chunkhash:6].js',
		crossOriginLoading: 'anonymous'
	},
	performance: {
		hints
	},
	resolve: {
		alias: {
			...isomorphicWebpackConfig.resolve.alias
			// NOTE: Preact + preact-compat can save you 148Kb parsed or 14kb gzipped
			// Preact may breaks your React app, starter by default doesn't aim to support Preact
			// react: 'preact-compat',
			// 'react-dom': 'preact-compat',
			// 'preact-compat': 'preact-compat/dist/preact-compat'
		},
		modules: isomorphicWebpackConfig.resolve.modules,
		extensions: isomorphicWebpackConfig.resolve.extensions.concat([
			'.css',
			'.scss',
			'.sass'
		])
	},
	module: {
		rules: isomorphicWebpackConfig.module.rules.concat([
			{
				test: /\.(ico|eot|otf|webp|ttf|woff|woff2)$/i,
				use: `file-loader?limit=100000&name=assets/[name].[hash:8].[ext]`
			},
			{
				test: /\.(jpe?g|png|gif|svg)$/,
				use: [
					{
						loader: 'url-loader',
						options: {
							limit: 4096,
							// path: '/images',
							name: 'images/[name].[hash:8].[ext]'
						}
					},
					'img-loader'
				]
			}
			// NOTE: LQIP loader doesn't work with file-loader and url-loader :(
			// `npm i --save-dev lqip-loader`
			// {
			//   test: /\.(jpe?g|png)$/i,
			//   enforce: 'pre',
			//   loaders: [
			//     {
			//       loader: 'lqip-loader',
			//       options: {
			//         path: '/images-lqip', // your image going to be in media folder in the output dir
			//         name: '[name]-lqip.[hash:8].[ext]' // you can use [hash].[ext] too if you wish
			//       }
			//     }
			//   ]
			// }
		])
	},
	plugins: isomorphicWebpackConfig.plugins.concat([
		new webpack.DefinePlugin(definePluginArgs),
		new AssetsPlugin({
			path: CLIENT_DIST_PATH
		}),
		// NOTE: this plugin is good, but there are few big issues:
		// 1. It sets invalid url to browserconfig.xml and manifest.json in index.html.
		// E.g: in generated index.html you can see:
		// <meta name="msapplication-config" content="browserconfig.xml">
		// 2. It looks like generated images aren't minified.(not sure)
		// NOTE: It would be better to generate favicons without this plugin.
		new FaviconsWebpackPlugin({
			// add theme-color property
			background: manifest.theme,
			prefix: `favicons/`,
			logo: path.join(rootPath, './static/images/Logo.png'),
			title,
			emitStats: true,
			statsFilename: 'favicons-stats.json',
			// Inject generated html into html-webpack-plugin
			inject: false,
			// which icons should be generated (see https://github.com/haydenbleasel/favicons#usage)
			icons: {
				android: false,
				appleIcon: true,
				appleStartup: false,
				coast: false,
				favicons: true,
				firefox: false,
				opengraph: false,
				twitter: true,
				yandex: false,
				windows: false
			}
		}),
		new WebpackAssetsManifest({
			assets: config.manifest
		})
	]),
	target: 'web'
}

export default baseBuild
<|endoftext|>


<commit_before>'use strict'

const fs = require('fs')
const opn = require('opn')
const url = require('url')
const http = require('http')
const exec = require('child_process').exec
const yargs = require('yargs')

class CLI {
  constructor (args) {
    this.parseArguments(args)
    this.port = this.args.extension || 1337
    this.prefix = 'ws://'
    this.devtools = 'chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws='
    this.image = { path: '../extension/icon.png', type: 'image/png' }
    this.index = { path: '../extension/index.html', type: 'text/html' }
    this.caught = false
    this.browser = `google chrome ${this.args.canary ? 'canary' : ''}`.trim()
  }

  get props () {
    return {
      args: this.args,
      browser: this.browser,
      port: this.port
    }
  }

  parseArguments (args) {
    this.args = yargs
      .version()
      .demandCommand(1)
      .usage('rawkit [options] <file ...>')
      .alias('v', 'version')
      .version(() => require('../package').version)
      .describe('v', 'show version information')
      .alias('h', 'help')
      .help('help')
      .usage('Usage: $0 -x [num]')
      .showHelpOnFail(false, 'Specify --help for available options')
      .option('canary', {
        alias: 'c',
        describe: 'Run the devtools in canary.',
        boolean: true
      })
      .option('inspect-brk', {
        alias: 'brk',
        describe: 'To break on the first line of the application code.',
        boolean: true
      })
      .option('silent', {
        alias: 's',
        describe: 'Hide stdout/stderr output from child process.',
        boolean: true
      })
      .option('extension', {
        alias: 'e',
        describe: 'Define a specific port to run the extension server on. Defaults to 1337.',
        type: 'number'
      })
      .parse(args)
  }

  parseURL (str) {
    let re = /(\b(ws?|chrome-devtools):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig
    let matches = str.match(re)
    let link = (matches) ? matches[0] : null
    let isNew = link && link.indexOf(this.prefix) >= 0
    return (isNew) ? `${this.prefix}${link.replace(this.prefix, '')}` : link
  }

  exec () {
    let o = process.argv
    let args = o.splice(o.indexOf(this.args._[2]), o.length).join(' ')
    let cmd = (this.args._.brk) ? '--inspect-brk' : '--inspect'
    this.child = exec(`node ${cmd} ${args}`, { shell: true })
    this.child.stdout.on('data', this.handle.bind(this))
    this.child.stderr.on('data', this.handle.bind(this))
    this.child.on('close', _ => process.exit())
    process.on('exit', _ => this.child.kill())
  }

  handle (data) {
    let ref = this.parseURL(data)
    if (!this.caught && ref && !this.args['no-prompt']) {
      let link = `http://localhost:${this.port}/?rawkit=${encodeURIComponent(ref)}`
      let opts = {
        app: [this.browser],
        wait: false
      }
      opn(link, opts)
        .then(() => {})
        .catch((e) => {})
      this.caught = true
    }
    if (!this.args.silent) {
      process.stdout.write(data)
    }
  }

  start () {
    this.server = http.createServer()
    this.server.on('request', (req, res) => {
      let request = url.parse(req.url, true)
      let image = request.pathname.indexOf('.png') >= 0
      let file = (image) ? this.image : this.index
      fs.readFile(file.path, (err, data) => {
        if (err) throw err
        res.writeHead(200, { 'Content-Type': file.type })
        if (image) {
          res.end(data, 'binary')
        } else {
          res.end(data.toString())
        }
      })
    }).listen(this.port)
  }
}

module.exports = (args) => {
  return new CLI(args)
}
<commit_msg>Resolve path name<commit_after>'use strict'

const fs = require('fs')
const opn = require('opn')
const url = require('url')
const path = require('path')
const http = require('http')
const exec = require('child_process').exec
const yargs = require('yargs')

class CLI {
  constructor (args) {
    this.parseArguments(args)
    this.port = this.args.extension || 1337
    this.prefix = 'ws://'
    this.devtools = 'chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws='
    this.image = { path: '../extension/icon.png', type: 'image/png' }
    this.index = { path: '../extension/index.html', type: 'text/html' }
    this.caught = false
    this.browser = `google chrome ${this.args.canary ? 'canary' : ''}`.trim()
  }

  get props () {
    return {
      args: this.args,
      browser: this.browser,
      port: this.port
    }
  }

  parseArguments (args) {
    this.args = yargs
      .version()
      .demandCommand(1)
      .usage('rawkit [options] <file ...>')
      .alias('v', 'version')
      .version(() => require('../package').version)
      .describe('v', 'show version information')
      .alias('h', 'help')
      .help('help')
      .usage('Usage: $0 -x [num]')
      .showHelpOnFail(false, 'Specify --help for available options')
      .option('canary', {
        alias: 'c',
        describe: 'Run the devtools in canary.',
        boolean: true
      })
      .option('inspect-brk', {
        alias: 'brk',
        describe: 'To break on the first line of the application code.',
        boolean: true
      })
      .option('silent', {
        alias: 's',
        describe: 'Hide stdout/stderr output from child process.',
        boolean: true
      })
      .option('extension', {
        alias: 'e',
        describe: 'Define a specific port to run the extension server on. Defaults to 1337.',
        type: 'number'
      })
      .parse(args)
  }

  parseURL (str) {
    let re = /(\b(ws?|chrome-devtools):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig
    let matches = str.match(re)
    let link = (matches) ? matches[0] : null
    let isNew = link && link.indexOf(this.prefix) >= 0
    return (isNew) ? `${this.prefix}${link.replace(this.prefix, '')}` : link
  }

  exec () {
    let o = process.argv
    let args = o.splice(o.indexOf(this.args._[2]), o.length).join(' ')
    let cmd = (this.args._.brk) ? '--inspect-brk' : '--inspect'
    this.child = exec(`node ${cmd} ${args}`, { shell: true })
    this.child.stdout.on('data', this.handle.bind(this))
    this.child.stderr.on('data', this.handle.bind(this))
    this.child.on('close', _ => process.exit())
    process.on('exit', _ => this.child.kill())
  }

  handle (data) {
    let ref = this.parseURL(data)
    if (!this.caught && ref && !this.args['no-prompt']) {
      let link = `http://localhost:${this.port}/?rawkit=${encodeURIComponent(ref)}`
      let opts = {
        app: [this.browser],
        wait: false
      }
      opn(link, opts)
        .then(() => {})
        .catch((e) => {})
      this.caught = true
    }
    if (!this.args.silent) {
      process.stdout.write(data)
    }
  }

  start () {
    this.server = http.createServer()
    this.server.on('request', (req, res) => {
      let request = url.parse(req.url, true)
      let image = request.pathname.indexOf('.png') >= 0
      let file = (image) ? this.image : this.index
      fs.readFile(path.resolve(__dirname, file.path), (err, data) => {
        if (err) throw err
        res.writeHead(200, { 'Content-Type': file.type })
        if (image) {
          res.end(data, 'binary')
        } else {
          res.end(data.toString())
        }
      })
    }).listen(this.port)
  }
}

module.exports = (args) => {
  return new CLI(args)
}
<|endoftext|>


<commit_before>import path from 'path';
import remark from 'remark';
import { read, write } from './fs';

export default function parser(dir = process.cwd()) {
    const pathname = path.resolve(dir, 'CHANGELOG.md');
    const contents = read(pathname);
    const parserOptions = {
        position: false
    };
    return {
        remark,
        root: remark.parse(contents, parserOptions),
        createMDAST(value) {
            const result = this.remark.parse(value, parserOptions);
            if (result.children.length === 1) {
                return result.children[0];
            }
            return result.children;
        },
        exists() {
            return contents !== null;
        },
        write() {
            return write(pathname, this.stringify());
        },
        stringify() {
            return this.remark.stringify(this.root, parserOptions);
        }
    };
}
<commit_msg>rollback parser position option<commit_after>import path from 'path';
import remark from 'remark';
import { read, write } from './fs';

export default function parser(dir = process.cwd()) {
    const pathname = path.resolve(dir, 'CHANGELOG.md');
    const contents = read(pathname);
    return {
        remark,
        root: remark.parse(contents),
        createMDAST(value) {
            const result = this.remark.parse(value);
            if (result.children.length === 1) {
                return result.children[0];
            }
            return result.children;
        },
        exists() {
            return contents !== null;
        },
        write() {
            return write(pathname, this.stringify());
        },
        stringify() {
            return this.remark.stringify(this.root);
        }
    };
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2014, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * https://raw.github.com/facebook/regenerator/master/LICENSE file. An
 * additional grant of patent rights can be found in the PATENTS file in
 * the same directory.
 */

var assert = require("assert");
var path = require("path");
var fs = require("fs");
var through = require("through");
var transform = require("./lib/visit").transform;
var utils = require("./lib/util");
var recast = require("recast");
var types = recast.types;
var genOrAsyncFunExp = /\bfunction\s*\*|\basync\b/;
var blockBindingExp = /\b(let|const)\s+/;

function exports(file, options) {
  var data = [];
  return through(write, end);

  function write(buf) {
    data.push(buf);
  }

  function end() {
    this.queue(compile(data.join(""), options).code);
    this.queue(null);
  }
}

// To get a writable stream for use as a browserify transform, call
// require("regenerator")().
module.exports = exports;

// To include the runtime globally in the current node process, call
// require("regenerator").runtime().
function runtime() {
  require("./runtime");
}
exports.runtime = runtime;
runtime.path = path.join(__dirname, "runtime.js");

function compile(source, options) {
  options = normalizeOptions(options);

  if (!genOrAsyncFunExp.test(source)) {
    return {
      // Shortcut: no generators or async functions to transform.
      code: (options.includeRuntime === true ? fs.readFileSync(
        path.join(__dirname, "runtime.js"), "utf-8"
      ) + "\n" : "") + source
    };
  }

  var recastOptions = getRecastOptions(options);
  var ast = recast.parse(source, recastOptions);
  var path = new types.NodePath(ast);
  var programPath = path.get("program");

  if (shouldVarify(source, options)) {
    // Transpile let/const into var declarations.
    varifyAst(programPath.node);
  }

  transform(programPath, options);

  return recast.print(path, recastOptions);
}

function normalizeOptions(options) {
  options = utils.defaults(options || {}, {
    includeRuntime: false,
    supportBlockBinding: true
  });

  if (!options.esprima) {
    options.esprima = require("esprima-fb");
  }

  assert.ok(
    /harmony/.test(options.esprima.version),
    "Bad esprima version: " + options.esprima.version
  );

  return options;
}

function getRecastOptions(options) {
  var recastOptions = {
    range: true
  };

  function copy(name) {
    if (name in options) {
      recastOptions[name] = options[name];
    }
  }

  copy("esprima");
  copy("sourceFileName");
  copy("sourceMapName");
  copy("inputSourceMap");
  copy("sourceRoot");

  return recastOptions;
}

function shouldVarify(source, options) {
  var supportBlockBinding = !!options.supportBlockBinding;
  if (supportBlockBinding) {
    if (!blockBindingExp.test(source)) {
      supportBlockBinding = false;
    }
  }

  return supportBlockBinding;
}

function varify(source, options) {
  var recastOptions = getRecastOptions(normalizeOptions(options));
  var ast = recast.parse(source, recastOptions);
  varifyAst(ast.program);
  return recast.print(ast, recastOptions).code;
}

function varifyAst(ast) {
  types.namedTypes.Program.assert(ast);

  var defsResult = require("defs")(ast, {
    ast: true,
    disallowUnknownReferences: false,
    disallowDuplicated: false,
    disallowVars: false,
    loopClosures: "iife"
  });

  if (defsResult.errors) {
    throw new Error(defsResult.errors.join("\n"))
  }

  return ast;
}

// Convenience for just translating let/const to var declarations.
exports.varify = varify;

// Transforms a string of source code, returning the { code, map? } result
// from recast.print.
exports.compile = compile;

// To modify an AST directly, call require("regenerator").transform(ast).
exports.transform = transform;
<commit_msg>Fix JS hoisting issue by using different var name<commit_after>/**
 * Copyright (c) 2014, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * https://raw.github.com/facebook/regenerator/master/LICENSE file. An
 * additional grant of patent rights can be found in the PATENTS file in
 * the same directory.
 */

var assert = require("assert");
var path = require("path");
var fs = require("fs");
var through = require("through");
var transform = require("./lib/visit").transform;
var utils = require("./lib/util");
var recast = require("recast");
var types = recast.types;
var genOrAsyncFunExp = /\bfunction\s*\*|\basync\b/;
var blockBindingExp = /\b(let|const)\s+/;

function exports(file, options) {
  var data = [];
  return through(write, end);

  function write(buf) {
    data.push(buf);
  }

  function end() {
    this.queue(compile(data.join(""), options).code);
    this.queue(null);
  }
}

// To get a writable stream for use as a browserify transform, call
// require("regenerator")().
module.exports = exports;

// To include the runtime globally in the current node process, call
// require("regenerator").runtime().
function runtime() {
  require("./runtime");
}
exports.runtime = runtime;
runtime.path = path.join(__dirname, "runtime.js");

function compile(source, options) {
  options = normalizeOptions(options);

  if (!genOrAsyncFunExp.test(source)) {
    return {
      // Shortcut: no generators or async functions to transform.
      code: (options.includeRuntime === true ? fs.readFileSync(
        path.join(__dirname, "runtime.js"), "utf-8"
      ) + "\n" : "") + source
    };
  }

  var recastOptions = getRecastOptions(options);
  var ast = recast.parse(source, recastOptions);
  var nodePath = new types.NodePath(ast);
  var programPath = nodePath.get("program");

  if (shouldVarify(source, options)) {
    // Transpile let/const into var declarations.
    varifyAst(programPath.node);
  }

  transform(programPath, options);

  return recast.print(nodePath, recastOptions);
}

function normalizeOptions(options) {
  options = utils.defaults(options || {}, {
    includeRuntime: false,
    supportBlockBinding: true
  });

  if (!options.esprima) {
    options.esprima = require("esprima-fb");
  }

  assert.ok(
    /harmony/.test(options.esprima.version),
    "Bad esprima version: " + options.esprima.version
  );

  return options;
}

function getRecastOptions(options) {
  var recastOptions = {
    range: true
  };

  function copy(name) {
    if (name in options) {
      recastOptions[name] = options[name];
    }
  }

  copy("esprima");
  copy("sourceFileName");
  copy("sourceMapName");
  copy("inputSourceMap");
  copy("sourceRoot");

  return recastOptions;
}

function shouldVarify(source, options) {
  var supportBlockBinding = !!options.supportBlockBinding;
  if (supportBlockBinding) {
    if (!blockBindingExp.test(source)) {
      supportBlockBinding = false;
    }
  }

  return supportBlockBinding;
}

function varify(source, options) {
  var recastOptions = getRecastOptions(normalizeOptions(options));
  var ast = recast.parse(source, recastOptions);
  varifyAst(ast.program);
  return recast.print(ast, recastOptions).code;
}

function varifyAst(ast) {
  types.namedTypes.Program.assert(ast);

  var defsResult = require("defs")(ast, {
    ast: true,
    disallowUnknownReferences: false,
    disallowDuplicated: false,
    disallowVars: false,
    loopClosures: "iife"
  });

  if (defsResult.errors) {
    throw new Error(defsResult.errors.join("\n"))
  }

  return ast;
}

// Convenience for just translating let/const to var declarations.
exports.varify = varify;

// Transforms a string of source code, returning the { code, map? } result
// from recast.print.
exports.compile = compile;

// To modify an AST directly, call require("regenerator").transform(ast).
exports.transform = transform;
<|endoftext|>


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

var entity2utf8 = require('../lib/entity2utf8'),
    log = require('../lib/log'),
    util = require('../lib/utils'),
    program = require('commander'),
    isutf8 = require('isutf8'),
    fs = require('fs'),
    files = [],
    comma = function(value) {
        return value.split(',').map(function(item) { return item.trim(); });
    };

program
    .version(require('../package.json').version)
    .usage('[options] <file...>')
    .option('--exts <file extensions>',
        'List of file extensions separated with commas. Example: ".txt,.html"', comma, [])
    .option('--ignore <entities>',
        'List of entities separated with commas. Example: " ,»,"', comma, [])
    .option('--replace', 'Replace entities to utf-8 symbols in files')
    .parse(process.argv);

if(!program.args.length) {
    program.help();
}

program.args.forEach(function(arg) {
    if(fs.existsSync(arg)) {
        files = files.concat(util.findFiles(arg, program.exts));
    } else {
        log.error(arg + ': is not exists');
    }
});

files.forEach(function(file) {
    var content = fs.readFileSync(file);
    if(!isutf8(content)) {
        log.error(file + ' not UTF-8.');
        return;
    }

    content = content.toString('utf8');

    var result = entity2utf8.find(content, program.ignore);
    if(result.length) {
        if(program.replace) {
            result = entity2utf8.replace(content, program.ignore);
            fs.writeFileSync(file, result);
        } else {
            log.errorNewLine(file);
            log.error('Need replace:');

            result.forEach(function(item) {
                log.error(item.original + ' → "' + item.replace + '"' +
                    (item.count > 1 ? ', count: ' + item.count : ''));
            });
        }
    }
});

if(!log.hasErrors() && !program.replace) {
    log.log('No errors.');
}

process.exit(log.hasErrors() ? 1 : 0);
<commit_msg>Fix codestyle<commit_after>#!/usr/bin/env node

var entity2utf8 = require('../lib/entity2utf8'),
    log = require('../lib/log'),
    util = require('../lib/utils'),
    program = require('commander'),
    isutf8 = require('isutf8'),
    fs = require('fs'),
    files = [],
    comma = function(value) {
        return value.split(',').map(function(item) { return item.trim(); });
    };

program
    .version(require('../package.json').version)
    .usage('[options] <file...>')
    .option('--exts <file extensions>',
        'List of file extensions separated with commas. Example: ".txt,.html"', comma, [])
    .option('--ignore <entities>',
        'List of entities separated with commas. Example: " ,»,"', comma, [])
    .option('--replace', 'Replace entities to utf-8 symbols in files')
    .parse(process.argv);

if(!program.args.length) {
    program.help();
}

program.args.forEach(function(arg) {
    if(fs.existsSync(arg)) {
        files = files.concat(util.findFiles(arg, program.exts));
    } else {
        log.error(arg + ': is not exists');
    }
});

files.forEach(function(file) {
    var content = fs.readFileSync(file);
    if(!isutf8(content)) {
        log.error(file + ' not UTF-8.');
        return;
    }

    content = content.toString('utf8');

    var result = entity2utf8.find(content, program.ignore);
    if(result.length) {
        if(program.replace) {
            result = entity2utf8.replace(content, program.ignore);
            fs.writeFileSync(file, result);
        } else {
            log.errorNewLine(file);
            log.error('Need replace:');

            result.forEach(function(item) {
                log.error(item.original + ' → "' + item.replace + '"' +
                    (item.count > 1 ? ', count: ' + item.count : ''));
            });
        }
    }
});

if(!log.hasErrors() && !program.replace) {
    log.log('No errors.');
}

process.exit(log.hasErrors() ? 1 : 0);
<|endoftext|>


<commit_before>var simplebug = simplebug || {};

simplebug.BugInfo = Backbone.Model.extend({
  urlRoot: function() {
    var url = "https://api-dev.bugzilla.mozilla.org/latest/bug/";
    var limit = "?include_fields=comments,url,summary,whiteboard,id";
    return url + this.get('bugID') + limit;
  },
  defaults: {
    domain: "http://www.example.com"
  },
  parse: function(response, options) {
    function getDomain(url) {
      var a = document.createElement('a');
      a.href = url;
      return a.hostname;
    }
    // stash whiteboard so BugComments model can peek at it
    simplebug.whiteboard = response.whiteboard || "";

    this.set({
      bugID: response.id,
      url:    response.url,
      domain: getDomain(response.url)
    });
  }
});

simplebug.BugComments = Backbone.Model.extend({
  urlRoot: function() {
    var url = "https://api-dev.bugzilla.mozilla.org/latest/bug/";
    var limit = "/comment";
    return url + this.get('bugID') + limit;
  },
  defaults: {
    suggestedfix: "The recommended way to detect Firefox and other mobile browsers is by searching for the string “Mobi”. This can be implemented through custom code or through a library/framework. If it is through a library/framework you can check that it is up to date or reach out to the vendor for more information. Mozilla Developer Network has detailed information on user agent detection."
  },
  description: function(type) {
      var type = type || "server or client";
      var copy = "This website is using " + type + " side user agent detection to determine if a user is browsing using a desktop or mobile client. Unfortunately the site is not properly detecting the user agent string for mobile Firefox browsers. This is causing Firefox mobile browsers to be redirected to the desktop version of the website rather than mobile."
      return copy;
  },
  parse: function(response, options) {
    this.set("firstComment", response.comments[0].raw_text.trim());
    this.getDescription(response);
    this.getSuggestedFix(response);
  },
  getTaggedComment: function(tag, comments) {
    var result = false;
    // loop from the bottom up. in case there are multiple results --
    // we only want the latest one.
    for (var i = comments.length - 1; i >= 0; i--) {
      if (comments[i].tags && comments[i].tags.indexOf(tag) != -1) {
        result = [tag, comments[i].text];
        break;
      }
    }
    // result is either a useful array, or `false`.
    return result;
  },
  getDefaultDescription: function() {
    if (simplebug.whiteboard && /(server|client)/.exec(simplebug.whiteboard)) {
      return this.description(RegExp.$1);
    }
  },
  getDescription: function(response) {
    // if any comment is tagged "description", use it.
    var descriptionTag = this.getTaggedComment("description", response.comments);
    if (descriptionTag) {
      this.set(descriptionTag[0], descriptionTag[1]);
    } else {
      // if first comment is tagged "simplebug-ignore", use default.
      // OR if the first comment is empty, use default.
      var ignoreTag = this.getTaggedComment("simplebug-ignore", response.comments);
      if (ignoreTag || this.get("firstComment") == "") {
        this.set("description", this.getDefaultDescription());
      } else {
        // Use first comment (which is the description in the Bugzilla UI)
        this.set("description", this.get("firstComment"));
      }
    }
  },
  getSuggestedFix: function(response){
    var suggestedfixTag = this.getTaggedComment("suggestedfix", response.comments);
    if (suggestedfixTag) {
        this.set(suggestedfixTag[0], suggestedfixTag[1]);
    } // otherwise it will use defaults.suggestedfix
  }
});

simplebug.HeaderView = Backbone.View.extend({
  tagName: 'h1',
  template: _.template($('#header-tmpl').html()),
  render: function() {
    this.$el.html(this.template(this.model.attributes));
    return this;
  }
});

simplebug.URLView = Backbone.View.extend({
  tagName: 'p',
  template: _.template($('#url-tmpl').html()),
  render: function() {
    this.$el.html(this.template(this.model.attributes));
    return this;
  }
});

simplebug.Description = Backbone.View.extend({
  template: _.template($('#description-tmpl').html()),
  render: function() {
    this.$el.html(this.template(this.model.attributes));
    return this;
  }
});

simplebug.SuggestedFix = Backbone.View.extend({
  template: _.template($('#suggestedfix-tmpl').html()),
  render: function() {
    this.$el.html(this.template(this.model.attributes));
    return this;
  }
});

simplebug.MoreInfo = Backbone.View.extend({
  tagName: 'p',
  template: _.template($('#information-tmpl').html()),
  render: function() {
    this.$el.html(this.template(this.model.attributes));
    return this;
  }
});

simplebug.MainView = Backbone.View.extend({
  el: $('#buginfo'),
  initialize: function() {
    $('#main-loader').show();
    $('#index').hide();
    // set up models
    this.bugInfo = new simplebug.BugInfo({bugID: this.options.bugID});
    this.bugComments = new simplebug.BugComments({bugID: this.options.bugID});
    this.initSubViews();
    this.fetchModels();
  },
  initSubViews: function() {
    this.url = new simplebug.URLView({model: this.bugInfo});
    this.header = new simplebug.HeaderView({model: this.bugInfo});
    this.moreInfo = new simplebug.MoreInfo({model: this.bugInfo});
    this.desc = new simplebug.Description({model: this.bugComments});
    this.suggestedFix = new simplebug.SuggestedFix({model: this.bugComments});
  },
  fetchModels: function() {
    var self = this;
    this.bugInfo.fetch().complete(function(){
      self.url.setElement(self.$('#url')).render();
      self.header.setElement(self.$('.general')).render();
      self.moreInfo.setElement(self.$('#information')).render();
      self.bugComments.fetch().complete(function(){
        self.desc.setElement(self.$('#description')).render();
        self.suggestedFix.setElement(self.$('#suggestedfix')).render();
        $('#main-loader').hide();
        // render() the MainView.
        // Note, we can move this up above this fetch() if we want to show
        // the explanation before we add in the description and suggestedfix
        // That makes the page feel faster, maybe.
        self.render();
      }).error(function(){console.log("TODO: actual error handling >_>");});
    }).error(function(){console.log("TODO: actual error handling >_>");});

  },
  render: function() {
    this.$el.show();
  }
});

simplebug.Router = Backbone.Router.extend({
    routes: {
        "": "index",
        "moz/:id":  "showBug"
    },
    initialize: function () {},
    index: function() {
      $('#main-loader').hide();
    },
    showBug: function(id) {
      //need to validate id.
      document.title = "Web Compatibility Error Report for " + id;
      this.mainView = new simplebug.MainView({bugID: id});
    }
});
//clean this up so it's not a ton of globals.
/* Let's get this party started. */
var router = new simplebug.Router();
Backbone.history.start();<commit_msg>Lets use mozilla instead of moz.<commit_after>var simplebug = simplebug || {};

simplebug.BugInfo = Backbone.Model.extend({
  urlRoot: function() {
    var url = "https://api-dev.bugzilla.mozilla.org/latest/bug/";
    var limit = "?include_fields=comments,url,summary,whiteboard,id";
    return url + this.get('bugID') + limit;
  },
  defaults: {
    domain: "http://www.example.com"
  },
  parse: function(response, options) {
    function getDomain(url) {
      var a = document.createElement('a');
      a.href = url;
      return a.hostname;
    }
    // stash whiteboard so BugComments model can peek at it
    simplebug.whiteboard = response.whiteboard || "";

    this.set({
      bugID:  response.id,
      url:    response.url,
      domain: getDomain(response.url)
    });
  }
});

simplebug.BugComments = Backbone.Model.extend({
  urlRoot: function() {
    var url = "https://api-dev.bugzilla.mozilla.org/latest/bug/";
    var limit = "/comment";
    return url + this.get('bugID') + limit;
  },
  defaults: {
    suggestedfix: "The recommended way to detect Firefox and other mobile browsers is by searching for the string “Mobi”. This can be implemented through custom code or through a library/framework. If it is through a library/framework you can check that it is up to date or reach out to the vendor for more information. Mozilla Developer Network has detailed information on user agent detection."
  },
  description: function(type) {
      var type = type || "server or client";
      var copy = "This website is using " + type + " side user agent detection to determine if a user is browsing using a desktop or mobile client. Unfortunately the site is not properly detecting the user agent string for mobile Firefox browsers. This is causing Firefox mobile browsers to be redirected to the desktop version of the website rather than mobile."
      return copy;
  },
  parse: function(response, options) {
    this.set("firstComment", response.comments[0].raw_text.trim());
    this.getDescription(response);
    this.getSuggestedFix(response);
  },
  getTaggedComment: function(tag, comments) {
    var result = false;
    // loop from the bottom up. in case there are multiple results --
    // we only want the latest one.
    for (var i = comments.length - 1; i >= 0; i--) {
      if (comments[i].tags && comments[i].tags.indexOf(tag) != -1) {
        result = [tag, comments[i].text];
        break;
      }
    }
    // result is either a useful array, or `false`.
    return result;
  },
  getDefaultDescription: function() {
    if (simplebug.whiteboard && /(server|client)/.exec(simplebug.whiteboard)) {
      return this.description(RegExp.$1);
    }
  },
  getDescription: function(response) {
    // if any comment is tagged "description", use it.
    var descriptionTag = this.getTaggedComment("description", response.comments);
    if (descriptionTag) {
      this.set(descriptionTag[0], descriptionTag[1]);
    } else {
      // if first comment is tagged "simplebug-ignore", use default.
      // OR if the first comment is empty, use default.
      var ignoreTag = this.getTaggedComment("simplebug-ignore", response.comments);
      if (ignoreTag || this.get("firstComment") == "") {
        this.set("description", this.getDefaultDescription());
      } else {
        // Use first comment (which is the description in the Bugzilla UI)
        this.set("description", this.get("firstComment"));
      }
    }
  },
  getSuggestedFix: function(response){
    var suggestedfixTag = this.getTaggedComment("suggestedfix", response.comments);
    if (suggestedfixTag) {
        this.set(suggestedfixTag[0], suggestedfixTag[1]);
    } // otherwise it will use defaults.suggestedfix
  }
});

simplebug.HeaderView = Backbone.View.extend({
  tagName: 'h1',
  template: _.template($('#header-tmpl').html()),
  render: function() {
    this.$el.html(this.template(this.model.attributes));
    return this;
  }
});

simplebug.URLView = Backbone.View.extend({
  tagName: 'p',
  template: _.template($('#url-tmpl').html()),
  render: function() {
    this.$el.html(this.template(this.model.attributes));
    return this;
  }
});

simplebug.Description = Backbone.View.extend({
  template: _.template($('#description-tmpl').html()),
  render: function() {
    this.$el.html(this.template(this.model.attributes));
    return this;
  }
});

simplebug.SuggestedFix = Backbone.View.extend({
  template: _.template($('#suggestedfix-tmpl').html()),
  render: function() {
    this.$el.html(this.template(this.model.attributes));
    return this;
  }
});

simplebug.MoreInfo = Backbone.View.extend({
  tagName: 'p',
  template: _.template($('#information-tmpl').html()),
  render: function() {
    this.$el.html(this.template(this.model.attributes));
    return this;
  }
});

simplebug.MainView = Backbone.View.extend({
  el: $('#buginfo'),
  initialize: function() {
    $('#main-loader').show();
    $('#index').hide();
    // set up models
    this.bugInfo = new simplebug.BugInfo({bugID: this.options.bugID});
    this.bugComments = new simplebug.BugComments({bugID: this.options.bugID});
    this.initSubViews();
    this.fetchModels();
  },
  initSubViews: function() {
    this.url = new simplebug.URLView({model: this.bugInfo});
    this.header = new simplebug.HeaderView({model: this.bugInfo});
    this.moreInfo = new simplebug.MoreInfo({model: this.bugInfo});
    this.desc = new simplebug.Description({model: this.bugComments});
    this.suggestedFix = new simplebug.SuggestedFix({model: this.bugComments});
  },
  fetchModels: function() {
    var self = this;
    this.bugInfo.fetch().complete(function(){
      self.url.setElement(self.$('#url')).render();
      self.header.setElement(self.$('.general')).render();
      self.moreInfo.setElement(self.$('#information')).render();
      self.bugComments.fetch().complete(function(){
        self.desc.setElement(self.$('#description')).render();
        self.suggestedFix.setElement(self.$('#suggestedfix')).render();
        $('#main-loader').hide();
        // render() the MainView.
        // Note, we can move this up above this fetch() if we want to show
        // the explanation before we add in the description and suggestedfix
        // That makes the page feel faster, maybe.
        self.render();
      }).error(function(){console.log("TODO: actual error handling >_>");});
    }).error(function(){console.log("TODO: actual error handling >_>");});

  },
  render: function() {
    this.$el.show();
  }
});

simplebug.Router = Backbone.Router.extend({
    routes: {
        "": "index",
        "mozilla/:id":  "showBug"
    },
    initialize: function () {},
    index: function() {
      $('#main-loader').hide();
    },
    showBug: function(id) {
      //need to validate id.
      document.title = "Web Compatibility Error Report for " + id;
      this.mainView = new simplebug.MainView({bugID: id});
    }
});
//clean this up so it's not a ton of globals.
/* Let's get this party started. */
var router = new simplebug.Router();
Backbone.history.start();<|endoftext|>