<commit_before>import { Juko8 } from 'CONTRIBUTORS';

import React from 'react';
import SPELLS from 'common/SPELLS';
import SpellLink from 'common/SpellLink';

export default [
  {
    date: new Date('2018-09-09'),
    changes: <>Added Azerite statistic for Swift Roundhouse.</>,
    contributors: [Juko8],
  },
  {
    date: new Date('2018-09-04'),
    changes: <>Added Azerite statistics for Iron Fists and Meridian Strikes.</>,
    contributors: [Juko8],
  },
  {
    date: new Date('2018-08-31'),
    changes: 'Removed "Casts in Storm, Earth and Fire/Serenity statistics" since it\'s no longer providing accurate analysis',
    contributors: [Juko8],
  },
  {
    date: new Date('2018-08-29'),
    changes: 'Removed legion legendaries and tiersets',
    contributors: [Juko8],
  },
  {
    date: new Date('2018-06-16'),
    changes: <>Updated for 8.0 Battle for Azeroth prepatch. All artifact traits and related analysis removed. Bad <SpellLink id={SPELLS.BLACKOUT_KICK.id} icon /> casts statistic and suggestions has been replaced with statistic and suggestions on <SpellLink id={SPELLS.BLACKOUT_KICK.id} icon />'s new cooldown reductions mechanic </>,
    contributors: [Juko8],
  },
];
<commit_msg>Update CHANGELOG.js<commit_after>import { Juko8 } from 'CONTRIBUTORS';

import React from 'react';
import SPELLS from 'common/SPELLS';
import SpellLink from 'common/SpellLink';

export default [
  {
    date: new Date('2019-01-02'),
    changes: <>Added Azerite statistic for <SpellLink id={SPELLS.FURY_OF_XUEN.id} />.</>,
    contributors: [Juko8],
  },
  {
    date: new Date('2018-12-27'),
    changes: <>Added Azerite statistic for <SpellLink id={SPELLS.GLORY_OF_THE_DAWN.id} />.</>,
    contributors: [Juko8],
  },
  {
    date: new Date('2018-09-09'),
    changes: 'Added Azerite statistic for Swift Roundhouse.',
    contributors: [Juko8],
  },
  {
    date: new Date('2018-09-04'),
    changes: 'Added Azerite statistics for Iron Fists and Meridian Strikes.',
    contributors: [Juko8],
  },
  {
    date: new Date('2018-08-31'),
    changes: 'Removed "Casts in Storm, Earth and Fire/Serenity statistics" since it\'s no longer providing accurate analysis',
    contributors: [Juko8],
  },
  {
    date: new Date('2018-08-29'),
    changes: 'Removed legion legendaries and tiersets',
    contributors: [Juko8],
  },
  {
    date: new Date('2018-06-16'),
    changes: <>Updated for 8.0 Battle for Azeroth prepatch. All artifact traits and related analysis removed. Bad <SpellLink id={SPELLS.BLACKOUT_KICK.id} icon /> casts statistic and suggestions has been replaced with statistic and suggestions on <SpellLink id={SPELLS.BLACKOUT_KICK.id} icon />'s new cooldown reductions mechanic </>,
    contributors: [Juko8],
  },
];
<|endoftext|>


<commit_before>/*!
 * ${copyright}
 */
/**
 * Defines support rules of the Tokenizer control of sap.m library.
 */
sap.ui.define(["sap/ui/support/library"],
function(SupportLib) {
	"use strict";

	// shortcuts
	var Categories = SupportLib.Categories, // Accessibility, Performance, Memory, ...
		Severity = SupportLib.Severity,	// Hint, Warning, Error
		Audiences = SupportLib.Audiences; // Control, Internal, Application

	var oTokenizerParentRule = {
			id : "tokenizerParentRule",
			audiences: [Audiences.Application],
			categories: [Categories.Usage],
			enabled: true,
			minversion: "1.28",
			title : "Tokenizer: Tokenizer parent control",
			description : "The tokenizer can only be used as part of MultiComboBox, MultiInput or ValueHelpDialog.",
			resolution : "Do not use the Tokenizer control standalone.",
			check : function(oIssueManager, oCoreFacade, oScope) {
				var oTokenizers = oScope.getElementsByClassName("sap.m.Tokenizer"),
					bParent,
					sParentControlName,
					oParent;
				oTokenizers.forEach(function (oTokenizer) {
					oParent = oTokenizer.getParent();
					sParentControlName = oParent && oParent.getMetadata().getName();
					bParent = oParent && sParentControlName === "sap.m.MultiInput" ||
								sParentControlName === "sap.m.MultiComboBox" ||
								// Value Help Dialog uses the tokenizer in a vertical layout
								(sParentControlName === "sap.ui.layout.VerticalLayout" &&
								oParent.hasStyleClass("compVHTokenizerHLayout"));

					if (!bParent) {
						oIssueManager.addIssue({
							severity: Severity.High,
							details: "Tokenizer with id: " + oTokenizer.getId() + " is not inside a MultiComboBox, MultiInput or ValueHelpDialog",
							context: {
								id: oTokenizer.getId()
							}
						});
					}
				});
			}
		};

	return [oTokenizerParentRule];
}, true);<commit_msg>[FIX] sap.m.Tokenizer: Support rule enhancement<commit_after>/*!
 * ${copyright}
 */
/**
 * Defines support rules of the Tokenizer control of sap.m library.
 */
sap.ui.define(["sap/ui/support/library"],
function(SupportLib) {
	"use strict";

	// shortcuts
	var Categories = SupportLib.Categories, // Accessibility, Performance, Memory, ...
		Severity = SupportLib.Severity,	// Hint, Warning, Error
		Audiences = SupportLib.Audiences; // Control, Internal, Application

	var oTokenizerParentRule = {
			id : "tokenizerParentRule",
			audiences: [Audiences.Application],
			categories: [Categories.Usage],
			enabled: true,
			minversion: "1.28",
			title : "Tokenizer: Tokenizer parent control",
			description : "The tokenizer can only be used as part of MultiComboBox, MultiInput or ValueHelpDialog.",
			resolution : "Do not use the Tokenizer control standalone.",
			check : function(oIssueManager, oCoreFacade, oScope) {
				var oTokenizers = oScope.getElementsByClassName("sap.m.Tokenizer"),
					bParent, oParent;
				oTokenizers.forEach(function (oTokenizer) {
					oParent = oTokenizer.getParent();
					bParent = oParent && oParent instanceof sap.m.MultiInput || oParent instanceof sap.m.MultiComboBox ||
								// Value Help Dialog uses the tokenizer in a vertical layout
								(oParent instanceof sap.ui.layout.VerticalLayout &&
								oParent.hasStyleClass("compVHTokenizerHLayout"));

					if (!bParent) {
						oIssueManager.addIssue({
							severity: Severity.High,
							details: "Tokenizer with id: " + oTokenizer.getId() + " is not inside a MultiComboBox, MultiInput or ValueHelpDialog",
							context: {
								id: oTokenizer.getId()
							}
						});
					}
				});
			}
		};

	return [oTokenizerParentRule];
}, true);<|endoftext|>


<commit_before>/*

*/

var moment = require('moment');
var Parser = require('../parser').Parser;
var ParsedResult = require('../../result').ParsedResult;

var PATTERN = /(\W|^)(?:within\s*)?([0-9]+|an?|half(?:\s*an?)?)\s*(minutes?|hours?|weeks?|days?|months?|years?)\s*(?:ago|before|earlier)(?=(?:\W|$))/i;
var STRICT_PATTERN = /(\W|^)(?:within\s*)?([0-9]+|an?)\s*(minutes?|hours?|days?)\s*ago(?=(?:\W|$))/i;

exports.Parser = function ENTimeAgoFormatParser(){
    Parser.apply(this, arguments);

    this.pattern = function() {
        return this.isStrictMode()? STRICT_PATTERN : PATTERN;
    }

    this.extract = function(text, ref, match, opt){

        if (match.index > 0 && text[match.index-1].match(/\w/)) return null;

        var text = match[0];
        text  = match[0].substr(match[1].length, match[0].length - match[1].length);
        index = match.index + match[1].length;

        var result = new ParsedResult({
            index: index,
            text: text,
            ref: ref,
        });

        var num = match[2];
        if(num === 'a' || num === 'an'){
            num = 1;
        } else if (num.match(/half/)) {
            num = 0.5;
        } else {
            num = parseInt(num);
        }

        var date = moment(ref);

        if (match[3].match(/hour/) || match[3].match(/minute/)) {
            if (match[3].match(/hour/)) {

                date.add(-num, 'hour');

            } else if (match[3].match(/minute/)) {

                date.add(-num, 'minute');
            }

            result.start.imply('day', date.date());
            result.start.imply('month', date.month() + 1);
            result.start.imply('year', date.year());
            result.start.assign('hour', date.hour());
            result.start.assign('minute', date.minute());
            result.tags['ENTimeAgoFormatParser'] = true;
            return result;
        }

        if (match[3].match(/week/)) {
            date.add(-num, 'week');

            result.start.imply('day', date.date());
            result.start.imply('month', date.month() + 1);
            result.start.imply('year', date.year());
            result.start.imply('weekday', date.day());
            return result;
        }

        if (match[3].match(/day/)) {
            date.add(-num, 'd');
        }

        if (match[3].match(/month/)) {
            date.add(-num, 'month');
        }

        if (match[3].match(/year/)) {

            date.add(-num, 'year');
        }

        result.start.assign('day', date.date());
        result.start.assign('month', date.month() + 1);
        result.start.assign('year', date.year());
        return result;

    };
}
<commit_msg>Add parsing for seconds in EN TimeAgo<commit_after>/*

*/

var moment = require('moment');
var Parser = require('../parser').Parser;
var ParsedResult = require('../../result').ParsedResult;

var PATTERN = /(\W|^)(?:within\s*)?([0-9]+|an?|half(?:\s*an?)?)\s*(seconds?|minutes?|hours?|weeks?|days?|months?|years?)\s*(?:ago|before|earlier)(?=(?:\W|$))/i;
var STRICT_PATTERN = /(\W|^)(?:within\s*)?([0-9]+|an?)\s*(seconds?|minutes?|hours?|days?)\s*ago(?=(?:\W|$))/i;

exports.Parser = function ENTimeAgoFormatParser(){
    Parser.apply(this, arguments);

    this.pattern = function() {
        return this.isStrictMode()? STRICT_PATTERN : PATTERN;
    }

    this.extract = function(text, ref, match, opt){

        if (match.index > 0 && text[match.index-1].match(/\w/)) return null;

        var text = match[0];
        text  = match[0].substr(match[1].length, match[0].length - match[1].length);
        index = match.index + match[1].length;

        var result = new ParsedResult({
            index: index,
            text: text,
            ref: ref,
        });

        var num = match[2];
        if(num === 'a' || num === 'an'){
            num = 1;
        } else if (num.match(/half/)) {
            num = 0.5;
        } else {
            num = parseInt(num);
        }

        var date = moment(ref);

        if (match[3].match(/hour|minute|second/)) {
            if (match[3].match(/hour/)) {

                date.add(-num, 'hour');

            } else if (match[3].match(/minute/)) {

                date.add(-num, 'minute');

            } else if (match[3].match(/second/)) {

                date.add(-num, 'second');
            }

            result.start.imply('day', date.date());
            result.start.imply('month', date.month() + 1);
            result.start.imply('year', date.year());
            result.start.assign('hour', date.hour());
            result.start.assign('minute', date.minute());
            result.start.assign('second', date.second());
            result.tags['ENTimeAgoFormatParser'] = true;
            return result;
        }

        if (match[3].match(/week/)) {
            date.add(-num, 'week');

            result.start.imply('day', date.date());
            result.start.imply('month', date.month() + 1);
            result.start.imply('year', date.year());
            result.start.imply('weekday', date.day());
            return result;
        }

        if (match[3].match(/day/)) {
            date.add(-num, 'd');
        }

        if (match[3].match(/month/)) {
            date.add(-num, 'month');
        }

        if (match[3].match(/year/)) {

            date.add(-num, 'year');
        }

        result.start.assign('day', date.date());
        result.start.assign('month', date.month() + 1);
        result.start.assign('year', date.year());
        return result;

    };
}
<|endoftext|>


<commit_before>// Validates the fields in all forms with a data-validate-form attribute.
// Each input with a data-validate attribute is validated. The value of the attribute defines the type of the input
import validateInput from '../validate-input';

export default () => {
    $('[data-validate-form]').each((i, e) => {
        const form = $(e);
        const inputsToValidate = form.find('[data-validate]');

        // Attach validation handlers to all the inputs
        inputsToValidate.each((index, el) => {
            const input = $(el);
            const inputType = input.attr('data-validate');

            if (!inputType) {
                return;
            }

            // Set errors after user leaves a field
            input.on('blur', (e) => {
                setErrorStates(input, validateInput(input));
            });

            // Always clear errors on focus
            input.on('focus', () => {
                setErrorStates(input, true);
            });
        });

        // Submit event handler
        form.find('input[type="submit"]').on('click', (event) => {
            event.preventDefault();

            // First, validate all the inputs, this takes care of the
            // case where a user hits submit before touching any fields
            inputsToValidate.each((index, el) => {
                const input = $(el);

                setErrorStates(input, validateInput(input));
            });

            const elementsWithError = form.find('input.error[data-validate]');

            if (!elementsWithError.length) {
                form.submit();
            }
        });
    })
}

// Set the display of inputs and input messages based on the validity of the input
function setErrorStates(input, isValid) {
    if (isValid) {
        // Need to remove the error class for the input and hide the message
        $(`#${input.attr('data-error-element-id')}`).removeClass('show');
        input.removeClass('error');
    } else {
        // Need to add the error class for the input and show the error message
        $(`#${input.attr('data-error-element-id')}`).addClass('show');
        input.addClass('error');
    }
}
<commit_msg>Changed form validation to happen on submit<commit_after>// Validates the fields in all forms with a data-validate-form attribute.
// Each input with a data-validate attribute is validated. The value of the attribute defines the type of the input
import validateInput from '../validate-input';

export default () => {
    $('[data-validate-form]').each((i, e) => {
        const form = $(e);
        const inputsToValidate = form.find('[data-validate]');

        // Attach validation handlers to all the inputs
        inputsToValidate.each((index, el) => {
            const input = $(el);
            const inputType = input.attr('data-validate');

            if (!inputType) {
                return;
            }

            // Always clear errors on focus
            input.on('focus', () => {
                setErrorStates(input, true);
            });
        });

        // Submit event handler
        form.find('input[type="submit"]').on('click', (event) => {
            event.preventDefault();

            // First, validate all the inputs, this takes care of the
            // case where a user hits submit before touching any fields
            inputsToValidate.each((index, el) => {
                const input = $(el);

                setErrorStates(input, validateInput(input));
            });

            const elementsWithError = form.find('input.error[data-validate]');

            if (!elementsWithError.length) {
                form.submit();
            }
        });
    })
}

// Set the display of inputs and input messages based on the validity of the input
function setErrorStates(input, isValid) {
    if (isValid) {
        // Need to remove the error class for the input and hide the message
        $(`#${input.attr('data-error-element-id')}`).removeClass('show');
        input.removeClass('error');
    } else {
        // Need to add the error class for the input and show the error message
        $(`#${input.attr('data-error-element-id')}`).addClass('show');
        input.addClass('error');
    }
}
<|endoftext|>


<commit_before>/*
 */
'use strict';
import { Dropdown } from '@entrylabs/tool';
import _cloneDeep from 'lodash/cloneDeep';
/*
 *
 */
Entry.FieldDropdownDynamic = class FieldDropdownDynamic extends Entry.FieldDropdown {
    constructor(content, blockView, index) {
        super(content, blockView, index, null, null, true);
        this._block = blockView.block;
        this._blockView = blockView;

        const box = new Entry.BoxModel();
        this.box = box;

        this.svgGroup = null;

        this._contents = content;

        if (content.needDeepCopy) {
            this._contents = _cloneDeep(content);
        }

        this._index = index;

        let { bgColor, textColor, arrowColor } = content;
        if (
            this._block.deletable === Entry.Block.DELETABLE_FALSE_LIGHTEN ||
            this._block.emphasized
        ) {
            arrowColor = blockView._fillColor;
        }

        this._arrowColor = arrowColor;
        this._textColor = textColor || '#FFFFFF';
        this._bgColor = bgColor;

        const menuName = this._contents.menuName;
        if (_.isFunction(menuName)) {
            this._menuGenerator = menuName;
        } else {
            this._menuName = menuName;
        }

        this._CONTENT_HEIGHT = this.getContentHeight(content.dropdownHeight);
        this._font_size = this.getFontSize(content.fontSize);

        this._ROUND = content.roundValue || 3;
        this.initialize(blockView);
    }

    initialize(blockView) {
        const promise = this.renderStart(blockView);
        if (
            blockView &&
            blockView.getBoard() &&
            blockView.getBoard().workspace &&
            blockView.getBoard().workspace.changeEvent
        ) {
            blockView.getBoard().workspace.changeEvent.attach(this, () => {
                this._updateValue(true);
            });
        }
        if (promise instanceof Promise) {
            promise.then(() => {
                blockView.alignContent(false);
            });
        }
    }

    _isBlockInBoardWhenFunctionEdit() {
        const view = this._block.getView() || { _board: {} };
        return view._board.suffix === 'board' && Entry.Func.isEdit;
    }

    getTextByValue(value) {
        if (this._isBlockInBoardWhenFunctionEdit()) {
            return this.textElement.textContent;
        }

        return super.getTextByValue(value);
    }

    async _updateValue(reDraw) {
        const object = this._block.getCode().object;
        let options = [];
        if (Entry.container) {
            if (this._menuName) {
                options = await Entry.container.getDropdownList(this._menuName, object);
            } else {
                options = await this._menuGenerator();
            }
        }

        this._contents.options = options;
        this._updateOptions();

        if (reDraw && this._menuName === 'variables' && !this._isBlockInBoardWhenFunctionEdit()) {
            this.value = undefined;
        }
        this.setValue(this.getOptionCheckedValue(), reDraw);
    }

    getTargetValue(key, useParent = false) {
        if (!key) {
            return;
        }
        const block = useParent ? this._block.thread._block : this._block;
        const { _schema, params: values = [] } = block || {};
        const { params = [] } = _schema || {};
        const idx = params.findIndex(({ dropdownSync }) => dropdownSync === key);
        return values[idx || 0];
    }

    getOptionCheckedValue() {
        const { options, defaultValue } = this._contents;
        let value = this.getValue();

        if (this._blockView.isInBlockMenu || !value || value == 'null') {
            value = options.length !== 0 && options[0] ? options[0][1] : null;
        }
        const matched = _.find(options, ([, cValue]) => cValue === value);
        if (!matched && defaultValue) {
            if (_.isFunction(defaultValue)) {
                return defaultValue(value, options);
            }
            return defaultValue;
        }
        return value;
    }

    renderOptions() {
        this.optionGroup = Entry.Dom('div', {
            class: 'entry-widget-dropdown',
            parent: $('body'),
        });
        const { options = [] } = this._contents;
        const convertedOptions = options.map(([key, value]) => [this._convert(key, value), value]);
        this.dropdownWidget = new Dropdown({
            data: {
                eventTypes: ['mousedown', 'touchstart', 'wheel'],
                items: convertedOptions,
                positionDom: this.svgGroup,
                onOutsideClick: () => {
                    this.destroyOption();
                },
            },
            container: this.optionGroup[0],
        }).on('select', (item) => {
            this.applyValue(item[1]);
            this.destroyOption();
            const { view = {} } = this._block.getThread();
            if (view.reDraw) {
                view.reDraw();
            } else {
                this._block.view.reDraw();
            }
        });
        this.optionDomCreated();
    }
};
<commit_msg>dropdownDynamic에서 파라미터 길이와 블록 길이가 맞춰지지 않는 경우가 생겨서 resize 도 추가한 applyValue함수로 변경.<commit_after>/*
 */
'use strict';
import { Dropdown } from '@entrylabs/tool';
import _cloneDeep from 'lodash/cloneDeep';
/*
 *
 */
Entry.FieldDropdownDynamic = class FieldDropdownDynamic extends Entry.FieldDropdown {
    constructor(content, blockView, index) {
        super(content, blockView, index, null, null, true);
        this._block = blockView.block;
        this._blockView = blockView;

        const box = new Entry.BoxModel();
        this.box = box;

        this.svgGroup = null;

        this._contents = content;

        if (content.needDeepCopy) {
            this._contents = _cloneDeep(content);
        }

        this._index = index;

        let { bgColor, textColor, arrowColor } = content;
        if (
            this._block.deletable === Entry.Block.DELETABLE_FALSE_LIGHTEN ||
            this._block.emphasized
        ) {
            arrowColor = blockView._fillColor;
        }

        this._arrowColor = arrowColor;
        this._textColor = textColor || '#FFFFFF';
        this._bgColor = bgColor;

        const menuName = this._contents.menuName;
        if (_.isFunction(menuName)) {
            this._menuGenerator = menuName;
        } else {
            this._menuName = menuName;
        }

        this._CONTENT_HEIGHT = this.getContentHeight(content.dropdownHeight);
        this._font_size = this.getFontSize(content.fontSize);

        this._ROUND = content.roundValue || 3;
        this.initialize(blockView);
    }

    initialize(blockView) {
        const promise = this.renderStart(blockView);
        if (
            blockView &&
            blockView.getBoard() &&
            blockView.getBoard().workspace &&
            blockView.getBoard().workspace.changeEvent
        ) {
            blockView.getBoard().workspace.changeEvent.attach(this, () => {
                this._updateValue(true);
            });
        }
        if (promise instanceof Promise) {
            promise.then(() => {
                blockView.alignContent(false);
            });
        }
    }

    _isBlockInBoardWhenFunctionEdit() {
        const view = this._block.getView() || { _board: {} };
        return view._board.suffix === 'board' && Entry.Func.isEdit;
    }

    getTextByValue(value) {
        if (this._isBlockInBoardWhenFunctionEdit()) {
            return this.textElement.textContent;
        }

        return super.getTextByValue(value);
    }

    async _updateValue(reDraw) {
        const object = this._block.getCode().object;
        let options = [];
        if (Entry.container) {
            if (this._menuName) {
                options = await Entry.container.getDropdownList(this._menuName, object);
            } else {
                options = await this._menuGenerator();
            }
        }

        this._contents.options = options;
        this._updateOptions();

        if (reDraw && this._menuName === 'variables' && !this._isBlockInBoardWhenFunctionEdit()) {
            this.value = undefined;
        }
        this.applyValue(this.getOptionCheckedValue(), reDraw);
    }

    getTargetValue(key, useParent = false) {
        if (!key) {
            return;
        }
        const block = useParent ? this._block.thread._block : this._block;
        const { _schema, params: values = [] } = block || {};
        const { params = [] } = _schema || {};
        const idx = params.findIndex(({ dropdownSync }) => dropdownSync === key);
        return values[idx || 0];
    }

    getOptionCheckedValue() {
        const { options, defaultValue } = this._contents;
        let value = this.getValue();

        if (this._blockView.isInBlockMenu || !value || value == 'null') {
            value = options.length !== 0 && options[0] ? options[0][1] : null;
        }
        const matched = _.find(options, ([, cValue]) => cValue === value);
        if (!matched && defaultValue) {
            if (_.isFunction(defaultValue)) {
                return defaultValue(value, options);
            }
            return defaultValue;
        }
        return value;
    }

    renderOptions() {
        this.optionGroup = Entry.Dom('div', {
            class: 'entry-widget-dropdown',
            parent: $('body'),
        });
        const { options = [] } = this._contents;
        const convertedOptions = options.map(([key, value]) => [this._convert(key, value), value]);
        this.dropdownWidget = new Dropdown({
            data: {
                eventTypes: ['mousedown', 'touchstart', 'wheel'],
                items: convertedOptions,
                positionDom: this.svgGroup,
                onOutsideClick: () => {
                    this.destroyOption();
                },
            },
            container: this.optionGroup[0],
        }).on('select', (item) => {
            this.applyValue(item[1]);
            this.destroyOption();
            const { view = {} } = this._block.getThread();
            if (view.reDraw) {
                view.reDraw();
            } else {
                this._block.view.reDraw();
            }
        });
        this.optionDomCreated();
    }
};
<|endoftext|>


<commit_before>// base.js
// 141211
// - initial version

// Disable enter to submit form
// http://stackoverflow.com/a/587575
function checkEnter(e){
	e = e || event;
	var txtArea = /textarea/i.test((e.target || e.srcElement).tagName);
	return txtArea || (e.keyCode || e.which || e.charCode || 0) !== 13;
}

var $overlay,
	$tooltip,
	$menu,
	csrftoken = $.cookie('csrftoken'),
	browser = {
		can : {
			placeholder: function() { return 'placeholder' in document.createElement('input'); }
		}
	},
	taggingJS_options = {
		'case-sensitive': true,
		'forbidden-chars': [','],
		'forbidden-chars-text': '이하의 문자는 사용할 수 없습니다:\n',
		'forbidden-words-text': '이하의 단어는 사용할 수 없습니다:\n',
		'no-duplicate-text': '이하의 태그는 이미 선택되어 있습니다:\n',
		'tag-char': '',
		'no-spacebar': true,
		'tag-on-blur': false
	},
	autocomplete_options = {
		'serviceUrl': '/x/t',
		'type': 'POST',
		'minChars': 2,
		'lookupLimit': 5,
		'formatResult': function(suggestion, currentValue) {
			return '' + $.Autocomplete.formatResult(suggestion, currentValue) + '' + suggestion.data + '';
		},
		'onSelect': function(suggestion) { this.focus(); },
		'zIndex': 1050
	}

$(function() {

	$window = $(window);
	$document = $(document);
	$body = $('body');
	$overlay = $('#overlay');
	$tooltip = $('#tooltip');
	$menu = $('.dropdown.container');

	$document
		.one('touchstart', function() {
			$('html').removeClass('no-touch');

			$document
				.off('mouseenter mouseleave', '.th')
				.off('mouseenter', '*[title]');

			$('.pscroll')
				.perfectScrollbar('destroy')
				.css('overflow', 'auto');
		})

		.on('keypress', '.type-zone', checkEnter)

		.on('click', '.dropdown.container .handle', function(e) {
			var $container = $(this).closest('.container');
			if(!$container.hasClass('open')) { $container.addClass('open');
			} else { $container.removeClass('open'); }
		})
		.on('mouseleave', '.dropdown.container', function() { if($(this).hasClass('open')) $(this).removeClass('open'); })
		.on('click', '.dropdown.container .handle[href=#]', function(e) { e.preventDefault(); })
		.on('mousedown', '.dropdown.container .close', function(e) {
			e.preventDefault();
			var $container = $(this).closest('.container');
			$container.removeClass('open');
		})

		.on('click', 'a.checkbox', function(e) {
			if($(this).attr('href') != '#') return true;

			e.preventDefault();

			if($(this).hasClass('radio')) {
				var $container = $(this).closest('.radio-container'),
					$input = $container.find('input[name=' + $container.data('input-name') + ']');

				$container.find('a.radio').removeClass('checked');
				$(this).addClass('checked');
				$input.val($(this).data('input-value'));
			} else {
				var $checkbox = $(this).prev('input[type=checkbox]');

				$(this).toggleClass('checked');
				$checkbox.prop('checked', !$checkbox.prop('checked'));
			}
		})

		.on('mouseenter', '.th', showTooltip)
		.on('mouseleave scroll', '.th', hideTooltip)
		.on('mouseenter', '*[title]', function(e) {
			if($(this).closest('.note-editor').length) return false;
			$(this)
				.data('title', $(this).attr('title'))
				.removeAttr('title')
				.addClass('th');
			showTooltip(e);
		});

	$('.article img').each(function() {
		if($(this).parents('a').length > 0) { return false; } else {
			var a = $('');

			a
				.addClass('imagecontainer')
				.attr('href', $(this).attr('src'))
				.attr('target', '_blank');

			$(this).wrap(a);
		}
	});

	$('input[type=checkbox]').each(function() {
		var $label;

		$label = $(this).closest('label').length ? $(this).closest('label') : $label;
		$label = $(this).next('label').length ? $(this).next('label') : $label;
		$label = $(this).prev('label').length ? $(this).prev('label') : $label;

		var $a = $('')
			.attr('href', '#')
			.addClass('checkbox')
			.html('')

		if($(this).prop('checked')) $a.addClass('checked');

		$a
			.insertAfter($label)
			.find('.label').append('' + $.trim($label.text()) + '');
		$(this).insertAfter($label);

		$(this).hide();
		$label.remove();
	});

	$('.post.item .label.meta.comments')
		.on('mouseenter', function() {
			var $item = $(this).closest('a.post.item');

			$item.attr('href', $item.attr('href') + '#comments');
		})
		.on('mouseleave', function() {
			var $item = $(this).closest('a.post.item');

			$item.attr('href', $item.attr('href').replace('#comments', ''));
		});

	$('.section.article.form form')
		.on('submit', function(e) {
			var text, editor = $('#id_contents');

			text = editor.editable('getHTML', false, true);
			text = Autolinker.link(text);

			editor.editable('destroy');
			editor.css('visibility', 'hidden');
			editor.garlic('destroy');
			editor.val(text);

			$('#tagbox').tagging('add');
			$tags.val($tagbox.tagging('getTags').join(','));

			$(this).on('submit', function(e) {
				e.preventDefault();
			});
		})
		.find('.category')
			.on('click', 'a.option', function(e) {
				e.preventDefault();
				$('.section.article.form .category option').filter('[value='+$(this).data('value')+']').prop('selected', true).trigger('change');
				$('.section.article.form .category .text').text($(this).text());
				$(this).closest('.dropdown.container').removeClass('open');
			})
			.each(function() {
				var option, $handle = $(''), $dropdown = $('
'), $ul = $('
');

				option = $(this).find('select option');

				$('')
					.html(''+$(this).data('text')+'')
					.addClass('text')
					.appendTo($handle);

				$('')
					.addClass('icon')
					.appendTo($handle);

				$handle
					.attr('href', '#')
					.addClass('handle label meta')
					.appendTo($(this));

				$('')
					.addClass('close')
					.attr('href', '#')
					.appendTo($dropdown);

				$('
')
					.addClass('tip top')
					.html('')
					.appendTo($dropdown);

				option.each(function() {
					var $li = $('
'), $a = $(''), value = $(this).attr('value');

					if(value == '') return true;

					if($(this).prop('selected')) $(this).closest('.dropdown.container').find('.handle .text span').text($(this).text());

					$('')
						.text($(this).text())
						.appendTo($a);

					$a
						.attr('href', '#')
						.addClass('option')
						.data('value', value)
						.appendTo($li);

					$li
						.addClass(BOARD_CATEGORIES[value])
						.appendTo($ul);
				});

				$('
')
					.append($ul)
					.appendTo($dropdown);

				$dropdown
					.addClass('dropdown menu')
					.appendTo($(this));

				$(this).find('select').hide();
			});

	if(!browser.can.placeholder()) {
		$('#form_login .field input').each(function() {
			$('')
				.attr('for', $(this).attr('id'))
				.append(''+$(this).attr('placeholder')+'')
				.insertAfter($(this).addClass('noplaceholder'));
		});
	}

	$('#form_login')
		.on('load focusin focusout', '.field input.noplaceholder', function() {
			if(this.value == '') { $(this).next('label').show();
			} else { $(this).next('label').hide(); }
		})
		.on('keypress', '.field input.noplaceholder', function() {
			$(this).next('label').hide();
		});

	$('.vote a').on('click', function(e) {
		e.preventDefault();
		vote('p', $(this).parent('.vote').data('target-id'), $(this));
	});

	$('.section.board')
		.on('click', '.search.button .label.meta.search', function(e) {
			var $nav = $(this).closest('.nav.bottom');

			if(!$('html').hasClass('no-touch') && $nav.hasClass('close')) {
				e.preventDefault();

				$nav
					.addClass('open')
					.removeClass('close');
			}
		})
		.on('click', '.search.button .label.meta.delete', function(e) {
			var $nav = $(this).closest('.nav.bottom');

			if(!$('html').hasClass('no-touch') && $nav.hasClass('open')) {
				e.preventDefault();

				$nav
					.removeClass('open')
					.addClass('close');
			}
		});

	$('.tabs')
		.on('click', '.tab.header a:not(.current)', function() {
			var $container = $(this).closest('.tabs'),
				target = $(this).attr('href').replace('#', '.');

			$container.find('.section').hide();
			$container.find(target).show();

			$container.find('.tab.header a').removeClass('current');
			$(this).addClass('current');

		})
});

function csrfSafeMethod(method) { return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); }

$.ajaxSetup({
	beforeSend: function(xhr, settings) {
		if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
			xhr.setRequestHeader("X-CSRFToken", csrftoken);
		}
	}
});

function showTooltip(e) {
	var $target = $(e.target).closest('.th');
	var position = $target.offset();

	var targetHeight = $target.outerHeight();
	var targetWidth = $target.outerWidth();

	var offsetY = 0;
	var offsetX = 0;

	var top;
	var left;

	var height;
	var width;

	var margin = 10;

	$tooltip.find('.container p').html($target.data('title').replace(/\\n/gi, '
'));
	$tooltip.find('.tip').removeAttr('style');

	top = position.top + targetHeight;
	left = position.left + targetWidth/2;

	height = $tooltip.height();
	width = $tooltip.width();

	if(top + height + margin > $window.height() + $window.scrollTop()) offsetY = -1*(targetHeight + height);

	offsetX = $window.width() + $window.scrollLeft() - left;

	if(offsetX - (width/2 + margin) < 0) {
		offsetX = offsetX - (width/2 + margin);
		if(width/2 + offsetX < 0 ) return false;
	} else if(offsetX + (width/2 + margin) > 0) {
		offsetX = offsetX + width/2 + margin - $window.width();
		if(offsetX < 0) offsetX = 0;
		if(width/2 - offsetX < 0 ) return false;
	} else { offsetX = 0; }

	$('.th-active').removeClass('th-active');
	$target.addClass('th-active');

	$tooltip
		.css({
			'top': top + offsetY,
			'left': left - width/2 + offsetX
		})
		.show()
		.stop()
		.animate({'opacity': 1}, 100)
		.find('.tip')
			.hide()
			.css('margin-left', -2*offsetX)
			.filter((offsetY >= 0) ? '.top' : '.bottom').show();
}

function hideTooltip() {
	$('.th-active').removeClass('th-active');

	$tooltip
		.stop()
		.animate({'opacity': 0}, 100, function() { $tooltip.hide(); });
}

function vote(type, target, button) {
	var vote, avote, work,
		$sibling_voted = button.siblings('.voted'),
		databox = {
			type: type,
			target: target,
			vote: null
		};

	work = button.hasClass('voted') ? '-' : '+';
	vote = button.hasClass('upvote') ? '+' : '-';
	avote = (vote == '+') ? '-' : '+';

	if(work == '+' && $sibling_voted.length) {
		$ajax_vote({type: type, target: target, vote: '-' + avote}, $sibling_voted)
			.done(function(data, status, xhr) {
				$ajax_vote({type: type, target: target, vote: work + vote})
					.done(function(data) { vote_callback(data, work, button); });

				vote_callback(data, '-', $sibling_voted);
			});
	} else { $ajax_vote({type: type, target: target, vote: work + vote}).done(function(data) { vote_callback(data, work, button); }); };
}

function vote_callback(data, work, button) {
	if(work == '+') { button.addClass('voted');
	} else { button.removeClass('voted'); }

	var $score = button.closest('.item').find('.meta.score');

	if(button.parents('.comment').length && data.current.total  >= 0) data.current.total = '+' + data.current.total;

	$score
		.attr('title', '+'+data.current.upvote+' / -'+data.current.downvote)
		.find('.text span').text(data.current.total);
}

function $ajax_vote(databox) {
	return $.ajax({
			type: 'POST',
			url: VOTE_AJAX_ENDPOINT,
			data: databox
		})
			.fail(function(xhr, status, error) {
				var response = xhr.responseJSON.status;
				switch(response) {
					case 'notauthenticated':
						alert('로그인한 사용자만 사용 가능한 기능입니다.');
						break;

					case 'alreadyhave':
						alert('이미 추천한 게시글 또는 댓글입니다.');
						break;

					default:
						alert('알 수 없는 문제가 발생하였습니다.');
						console.log(databox);
						console.log(xhr);
						console.log(status);
						console.log(error);
				}
			});
}
<commit_msg>Fix image auto-link behavior<commit_after>// base.js
// 141211
// - initial version

// Disable enter to submit form
// http://stackoverflow.com/a/587575
function checkEnter(e){
	e = e || event;
	var txtArea = /textarea/i.test((e.target || e.srcElement).tagName);
	return txtArea || (e.keyCode || e.which || e.charCode || 0) !== 13;
}

var $overlay,
	$tooltip,
	$menu,
	csrftoken = $.cookie('csrftoken'),
	browser = {
		can : {
			placeholder: function() { return 'placeholder' in document.createElement('input'); }
		}
	},
	taggingJS_options = {
		'case-sensitive': true,
		'forbidden-chars': [','],
		'forbidden-chars-text': '이하의 문자는 사용할 수 없습니다:\n',
		'forbidden-words-text': '이하의 단어는 사용할 수 없습니다:\n',
		'no-duplicate-text': '이하의 태그는 이미 선택되어 있습니다:\n',
		'tag-char': '',
		'no-spacebar': true,
		'tag-on-blur': false
	},
	autocomplete_options = {
		'serviceUrl': '/x/t',
		'type': 'POST',
		'minChars': 2,
		'lookupLimit': 5,
		'formatResult': function(suggestion, currentValue) {
			return '' + $.Autocomplete.formatResult(suggestion, currentValue) + '' + suggestion.data + '';
		},
		'onSelect': function(suggestion) { this.focus(); },
		'zIndex': 1050
	}

$(function() {

	$window = $(window);
	$document = $(document);
	$body = $('body');
	$overlay = $('#overlay');
	$tooltip = $('#tooltip');
	$menu = $('.dropdown.container');

	$document
		.one('touchstart', function() {
			$('html').removeClass('no-touch');

			$document
				.off('mouseenter mouseleave', '.th')
				.off('mouseenter', '*[title]');

			$('.pscroll')
				.perfectScrollbar('destroy')
				.css('overflow', 'auto');
		})

		.on('keypress', '.type-zone', checkEnter)

		.on('click', '.dropdown.container .handle', function(e) {
			var $container = $(this).closest('.container');
			if(!$container.hasClass('open')) { $container.addClass('open');
			} else { $container.removeClass('open'); }
		})
		.on('mouseleave', '.dropdown.container', function() { if($(this).hasClass('open')) $(this).removeClass('open'); })
		.on('click', '.dropdown.container .handle[href=#]', function(e) { e.preventDefault(); })
		.on('mousedown', '.dropdown.container .close', function(e) {
			e.preventDefault();
			var $container = $(this).closest('.container');
			$container.removeClass('open');
		})

		.on('click', 'a.checkbox', function(e) {
			if($(this).attr('href') != '#') return true;

			e.preventDefault();

			if($(this).hasClass('radio')) {
				var $container = $(this).closest('.radio-container'),
					$input = $container.find('input[name=' + $container.data('input-name') + ']');

				$container.find('a.radio').removeClass('checked');
				$(this).addClass('checked');
				$input.val($(this).data('input-value'));
			} else {
				var $checkbox = $(this).prev('input[type=checkbox]');

				$(this).toggleClass('checked');
				$checkbox.prop('checked', !$checkbox.prop('checked'));
			}
		})

		.on('mouseenter', '.th', showTooltip)
		.on('mouseleave scroll', '.th', hideTooltip)
		.on('mouseenter', '*[title]', function(e) {
			if($(this).closest('.note-editor').length) return false;
			$(this)
				.data('title', $(this).attr('title'))
				.removeAttr('title')
				.addClass('th');
			showTooltip(e);
		});

	$('.section.article.detail div.article img').each(function() {
		if($(this).parents('a').length > 0) { return false; } else {
			var a = $('');

			a
				.addClass('imagecontainer')
				.attr('href', $(this).attr('src'))
				.attr('target', '_blank');

			$(this).wrap(a);
		}
	});

	$('input[type=checkbox]').each(function() {
		var $label;

		$label = $(this).closest('label').length ? $(this).closest('label') : $label;
		$label = $(this).next('label').length ? $(this).next('label') : $label;
		$label = $(this).prev('label').length ? $(this).prev('label') : $label;

		var $a = $('')
			.attr('href', '#')
			.addClass('checkbox')
			.html('')

		if($(this).prop('checked')) $a.addClass('checked');

		$a
			.insertAfter($label)
			.find('.label').append('' + $.trim($label.text()) + '');
		$(this).insertAfter($label);

		$(this).hide();
		$label.remove();
	});

	$('.post.item .label.meta.comments')
		.on('mouseenter', function() {
			var $item = $(this).closest('a.post.item');

			$item.attr('href', $item.attr('href') + '#comments');
		})
		.on('mouseleave', function() {
			var $item = $(this).closest('a.post.item');

			$item.attr('href', $item.attr('href').replace('#comments', ''));
		});

	$('.section.article.form form')
		.on('submit', function(e) {
			var text, editor = $('#id_contents');

			text = editor.editable('getHTML', false, true);
			text = Autolinker.link(text);

			editor.editable('destroy');
			editor.css('visibility', 'hidden');
			editor.garlic('destroy');
			editor.val(text);

			$('#tagbox').tagging('add');
			$tags.val($tagbox.tagging('getTags').join(','));

			$(this).on('submit', function(e) {
				e.preventDefault();
			});
		})
		.find('.category')
			.on('click', 'a.option', function(e) {
				e.preventDefault();
				$('.section.article.form .category option').filter('[value='+$(this).data('value')+']').prop('selected', true).trigger('change');
				$('.section.article.form .category .text').text($(this).text());
				$(this).closest('.dropdown.container').removeClass('open');
			})
			.each(function() {
				var option, $handle = $(''), $dropdown = $('
'), $ul = $('
');

				option = $(this).find('select option');

				$('')
					.html(''+$(this).data('text')+'')
					.addClass('text')
					.appendTo($handle);

				$('')
					.addClass('icon')
					.appendTo($handle);

				$handle
					.attr('href', '#')
					.addClass('handle label meta')
					.appendTo($(this));

				$('')
					.addClass('close')
					.attr('href', '#')
					.appendTo($dropdown);

				$('
')
					.addClass('tip top')
					.html('')
					.appendTo($dropdown);

				option.each(function() {
					var $li = $('
'), $a = $(''), value = $(this).attr('value');

					if(value == '') return true;

					if($(this).prop('selected')) $(this).closest('.dropdown.container').find('.handle .text span').text($(this).text());

					$('')
						.text($(this).text())
						.appendTo($a);

					$a
						.attr('href', '#')
						.addClass('option')
						.data('value', value)
						.appendTo($li);

					$li
						.addClass(BOARD_CATEGORIES[value])
						.appendTo($ul);
				});

				$('
')
					.append($ul)
					.appendTo($dropdown);

				$dropdown
					.addClass('dropdown menu')
					.appendTo($(this));

				$(this).find('select').hide();
			});

	if(!browser.can.placeholder()) {
		$('#form_login .field input').each(function() {
			$('')
				.attr('for', $(this).attr('id'))
				.append(''+$(this).attr('placeholder')+'')
				.insertAfter($(this).addClass('noplaceholder'));
		});
	}

	$('#form_login')
		.on('load focusin focusout', '.field input.noplaceholder', function() {
			if(this.value == '') { $(this).next('label').show();
			} else { $(this).next('label').hide(); }
		})
		.on('keypress', '.field input.noplaceholder', function() {
			$(this).next('label').hide();
		});

	$('.vote a').on('click', function(e) {
		e.preventDefault();
		vote('p', $(this).parent('.vote').data('target-id'), $(this));
	});

	$('.section.board')
		.on('click', '.search.button .label.meta.search', function(e) {
			var $nav = $(this).closest('.nav.bottom');

			if(!$('html').hasClass('no-touch') && $nav.hasClass('close')) {
				e.preventDefault();

				$nav
					.addClass('open')
					.removeClass('close');
			}
		})
		.on('click', '.search.button .label.meta.delete', function(e) {
			var $nav = $(this).closest('.nav.bottom');

			if(!$('html').hasClass('no-touch') && $nav.hasClass('open')) {
				e.preventDefault();

				$nav
					.removeClass('open')
					.addClass('close');
			}
		});

	$('.tabs')
		.on('click', '.tab.header a:not(.current)', function() {
			var $container = $(this).closest('.tabs'),
				target = $(this).attr('href').replace('#', '.');

			$container.find('.section').hide();
			$container.find(target).show();

			$container.find('.tab.header a').removeClass('current');
			$(this).addClass('current');

		})
});

function csrfSafeMethod(method) { return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); }

$.ajaxSetup({
	beforeSend: function(xhr, settings) {
		if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
			xhr.setRequestHeader("X-CSRFToken", csrftoken);
		}
	}
});

function showTooltip(e) {
	var $target = $(e.target).closest('.th');
	var position = $target.offset();

	var targetHeight = $target.outerHeight();
	var targetWidth = $target.outerWidth();

	var offsetY = 0;
	var offsetX = 0;

	var top;
	var left;

	var height;
	var width;

	var margin = 10;

	$tooltip.find('.container p').html($target.data('title').replace(/\\n/gi, '
'));
	$tooltip.find('.tip').removeAttr('style');

	top = position.top + targetHeight;
	left = position.left + targetWidth/2;

	height = $tooltip.height();
	width = $tooltip.width();

	if(top + height + margin > $window.height() + $window.scrollTop()) offsetY = -1*(targetHeight + height);

	offsetX = $window.width() + $window.scrollLeft() - left;

	if(offsetX - (width/2 + margin) < 0) {
		offsetX = offsetX - (width/2 + margin);
		if(width/2 + offsetX < 0 ) return false;
	} else if(offsetX + (width/2 + margin) > 0) {
		offsetX = offsetX + width/2 + margin - $window.width();
		if(offsetX < 0) offsetX = 0;
		if(width/2 - offsetX < 0 ) return false;
	} else { offsetX = 0; }

	$('.th-active').removeClass('th-active');
	$target.addClass('th-active');

	$tooltip
		.css({
			'top': top + offsetY,
			'left': left - width/2 + offsetX
		})
		.show()
		.stop()
		.animate({'opacity': 1}, 100)
		.find('.tip')
			.hide()
			.css('margin-left', -2*offsetX)
			.filter((offsetY >= 0) ? '.top' : '.bottom').show();
}

function hideTooltip() {
	$('.th-active').removeClass('th-active');

	$tooltip
		.stop()
		.animate({'opacity': 0}, 100, function() { $tooltip.hide(); });
}

function vote(type, target, button) {
	var vote, avote, work,
		$sibling_voted = button.siblings('.voted'),
		databox = {
			type: type,
			target: target,
			vote: null
		};

	work = button.hasClass('voted') ? '-' : '+';
	vote = button.hasClass('upvote') ? '+' : '-';
	avote = (vote == '+') ? '-' : '+';

	if(work == '+' && $sibling_voted.length) {
		$ajax_vote({type: type, target: target, vote: '-' + avote}, $sibling_voted)
			.done(function(data, status, xhr) {
				$ajax_vote({type: type, target: target, vote: work + vote})
					.done(function(data) { vote_callback(data, work, button); });

				vote_callback(data, '-', $sibling_voted);
			});
	} else { $ajax_vote({type: type, target: target, vote: work + vote}).done(function(data) { vote_callback(data, work, button); }); };
}

function vote_callback(data, work, button) {
	if(work == '+') { button.addClass('voted');
	} else { button.removeClass('voted'); }

	var $score = button.closest('.item').find('.meta.score');

	if(button.parents('.comment').length && data.current.total  >= 0) data.current.total = '+' + data.current.total;

	$score
		.attr('title', '+'+data.current.upvote+' / -'+data.current.downvote)
		.find('.text span').text(data.current.total);
}

function $ajax_vote(databox) {
	return $.ajax({
			type: 'POST',
			url: VOTE_AJAX_ENDPOINT,
			data: databox
		})
			.fail(function(xhr, status, error) {
				var response = xhr.responseJSON.status;
				switch(response) {
					case 'notauthenticated':
						alert('로그인한 사용자만 사용 가능한 기능입니다.');
						break;

					case 'alreadyhave':
						alert('이미 추천한 게시글 또는 댓글입니다.');
						break;

					default:
						alert('알 수 없는 문제가 발생하였습니다.');
						console.log(databox);
						console.log(xhr);
						console.log(status);
						console.log(error);
				}
			});
}
<|endoftext|>


<commit_before>/*
 *
 * * Copyright 2015 Acrolinx GmbH
 * *
 * * Licensed under the Apache License, Version 2.0 (the "License");
 * * you may not use this file except in compliance with the License.
 * * You may obtain a copy of the License at
 * *
 * * http://www.apache.org/licenses/LICENSE-2.0
 * *
 * * Unless required by applicable law or agreed to in writing, software
 * * distributed under the License is distributed on an "AS IS" BASIS,
 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * * See the License for the specific language governing permissions and
 * * limitations under the License.
 * *
 * * For more information visit: http://www.acrolinx.com
 *
 */

'use strict';
var AcrolinxPlugin = (function () {

    var clientComponents = [
        {
            id: 'com.acrolinx.sidebarexample',
            name: 'Acrolinx Sidebar Example Client',
            version: '1.2.3.999',
            category: 'MAIN'
        }
    ];

    function initAcrolinxSamplePlugin(config, editorAdapter) {
        var $sidebarContainer = $('#' + config.sidebarContainerId);
        var $sidebar = $('');
        $sidebarContainer.append($sidebar);
        var sidebarContentWindow = $sidebar.get(0).contentWindow;

        var adapter = editorAdapter;

        function onSidebarLoaded() {
            function initSidebarCloud() {
                config.requestAccessTokenCallback(function (accessToken) {
                    sidebarContentWindow.acrolinxSidebar.init({
                        clientComponents: config.clientComponents || clientComponents,
                        token: accessToken,
                        contentPieceUuid: config.documentId,
                        integrationFacadeBaseUrl: config.integrationFacadeBaseUrl
                    });
                });
            }

            function initSidebarOnPremise() {
                sidebarContentWindow.acrolinxSidebar.init({
                    clientComponents: config.clientComponents || clientComponents,
                    clientSignature: config.clientSignature,
                    showServerSelector: config.showServerSelector || true,
                    serverAddress: config.serverAddress

                    // These settings are only effective on servers with disabled checking profiles.
                    //checkSettings: {
                    //  'language': 'en',
                    //  'ruleSetName': 'Plain English',
                    //  'termSets': ['Medical'],
                    //  'checkSpelling': true,
                    //  'checkGrammar': true,
                    //  'checkStyle': true,
                    //  'checkReuse': false,
                    //  'harvestTerms': false,
                    //  'checkSeo': false,
                    //  'termStatuses': ['TERMINOLOGY_DEPRECATED']
                    //}

                    // These settings are only effective on servers with disabled checking profiles.
                    //defaultCheckSettings: {
                    //  'language': 'en',
                    //  'ruleSetName': 'Plain English',
                    //  'termSets': ['Medical'],
                    //  'checkSpelling': true,
                    //  'checkGrammar': true,
                    //  'checkStyle': true,
                    //  'checkReuse': false,
                    //  'harvestTerms': false,
                    //  'checkSeo': false,
                    //  'termStatuses': ['TERMINOLOGY_DEPRECATED']
                    //}

                });
            }

            console.log('Install acrolinxPlugin in sidebar.');
            sidebarContentWindow.acrolinxPlugin = {

                requestInit: function () {
                    console.log('requestInit');
                    if (config.sidebarType === 'CLOUD') {
                        initSidebarCloud();
                    } else {
                        initSidebarOnPremise();
                    }
                },

                onInitFinished: function (initFinishedResult) {
                    console.log('onInitFinished: ', initFinishedResult);
                    if (initFinishedResult.error) {
                        window.alert(initFinishedResult.error.message);
                    }
                },

                configure: function (configuration) {
                    console.log('configure: ', configuration);
                },

                requestAccessToken: function () {
                    var requestAccessTokenCallback = config.requestAccessTokenCallback;
                    if (requestAccessTokenCallback) {
                        requestAccessTokenCallback(function (accessToken) {
                            sidebarContentWindow.acrolinxSidebar.setAccessToken(accessToken);
                        });
                    }
                },

                requestGlobalCheckSync: function (html, format, documentReference) {
                    if (html.hasOwnProperty("error")) {
                        window.alert(html.error);
                    } else {
                        var checkInfo = sidebarContentWindow.acrolinxSidebar.checkGlobal(html.html, {
                            inputFormat: format || 'HTML',
                            requestDescription: {
                                documentReference: documentReference || 'filename.html'
                            }
                        });
                        adapter.registerCheckCall(checkInfo);
                    }

                },

                requestGlobalCheck: function () {
                    console.log('requestGlobalCheck');
                    var pHtml = adapter.extractHTMLForCheck();
                    var pFormat = adapter.getFormat ? adapter.getFormat() : null;
                    var pDocumentReference = adapter.getDocumentReference ? adapter.getDocumentReference() : null;
                    if (pHtml.then !== undefined) {
                        var self = this;
                        pHtml.then(function (html) {
                            self.requestGlobalCheckSync(html, pFormat, pDocumentReference);
                        });
                    } else {
                        this.requestGlobalCheckSync(pHtml, pFormat, pDocumentReference);

                    }
                },

                onCheckResult: function (checkResult) {
                    return adapter.registerCheckResult(checkResult);
                },

                selectRanges: function (checkId, matches) {
                    console.log('selectRanges: ', checkId, matches);
                    adapter.selectRanges(checkId, matches);

                },

                replaceRanges: function (checkId, matchesWithReplacement) {
                    console.log('replaceRanges: ', checkId, matchesWithReplacement);
                    adapter.replaceRanges(checkId, matchesWithReplacement);

                },

                // only needed for local checks
                getRangesOrder: function (checkedDocumentRanges) {
                    console.log('getRangesOrder: ', checkedDocumentRanges);
                    return [];
                },

                download: function (download) {
                    console.log('download: ', download.url, download);
                    window.open(download.url);
                },

                // only needed for local checks
                verifyRanges: function (checkedDocumentParts) {
                    console.log('verifyRanges: ', checkedDocumentParts);
                    return [];
                },

                disposeCheck: function (checkId) {
                    console.log('disposeCheck: ', checkId);
                }
            };

        }

        function loadSidebarIntoIFrame() {
            var sidebarBaseUrl = config.sidebarType === 'CLOUD' ?
                'https://acrolinx-integrations.acrolinx-cloud.com/sidebar/v13/' :
                'https://acrolinx-sidebar-classic.s3.amazonaws.com/v13/prod/';
            return $.ajax({
                url: sidebarBaseUrl + 'index.html'
            }).then(function (sidebarHtml) {
                var sidebarHtmlWithAbsoluteLinks = sidebarHtml
                    .replace(/src="/g, 'src="' + sidebarBaseUrl)
                    .replace(/href="/g, 'href="' + sidebarBaseUrl);
                sidebarContentWindow.document.open();
                sidebarContentWindow.document.write(sidebarHtmlWithAbsoluteLinks);
                sidebarContentWindow.document.close();
                onSidebarLoaded();
            });
        }

        loadSidebarIntoIFrame();
    }

    var cls = function (conf) {
        this.config = conf;
    };

    cls.prototype = {

        registerAdapter: function (adapter) {
            this.adapter = adapter;
        },

        init: function () {
            initAcrolinxSamplePlugin(this.config, this.adapter);
        }
    };

    return cls;

})();<commit_msg>DEV-3333 fixed problem if on config reading value for showServerSelector<commit_after>/*
 *
 * * Copyright 2015 Acrolinx GmbH
 * *
 * * Licensed under the Apache License, Version 2.0 (the "License");
 * * you may not use this file except in compliance with the License.
 * * You may obtain a copy of the License at
 * *
 * * http://www.apache.org/licenses/LICENSE-2.0
 * *
 * * Unless required by applicable law or agreed to in writing, software
 * * distributed under the License is distributed on an "AS IS" BASIS,
 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * * See the License for the specific language governing permissions and
 * * limitations under the License.
 * *
 * * For more information visit: http://www.acrolinx.com
 *
 */

'use strict';
var AcrolinxPlugin = (function () {

    var clientComponents = [
        {
            id: 'com.acrolinx.sidebarexample',
            name: 'Acrolinx Sidebar Example Client',
            version: '1.2.3.999',
            category: 'MAIN'
        }
    ];

    function initAcrolinxSamplePlugin(config, editorAdapter) {
        var $sidebarContainer = $('#' + config.sidebarContainerId);
        var $sidebar = $('');
        $sidebarContainer.append($sidebar);
        var sidebarContentWindow = $sidebar.get(0).contentWindow;

        var adapter = editorAdapter;

        function onSidebarLoaded() {
            function initSidebarCloud() {
                config.requestAccessTokenCallback(function (accessToken) {
                    sidebarContentWindow.acrolinxSidebar.init({
                        clientComponents: config.clientComponents || clientComponents,
                        token: accessToken,
                        contentPieceUuid: config.documentId,
                        integrationFacadeBaseUrl: config.integrationFacadeBaseUrl
                    });
                });
            }

            function initSidebarOnPremise() {
                sidebarContentWindow.acrolinxSidebar.init({
                    clientComponents: config.clientComponents || clientComponents,
                    clientSignature: config.clientSignature,
                    showServerSelector: config.showServerSelector !== null ? config.showServerSelector : true,
                    serverAddress: config.serverAddress

                    // These settings are only effective on servers with disabled checking profiles.
                    //checkSettings: {
                    //  'language': 'en',
                    //  'ruleSetName': 'Plain English',
                    //  'termSets': ['Medical'],
                    //  'checkSpelling': true,
                    //  'checkGrammar': true,
                    //  'checkStyle': true,
                    //  'checkReuse': false,
                    //  'harvestTerms': false,
                    //  'checkSeo': false,
                    //  'termStatuses': ['TERMINOLOGY_DEPRECATED']
                    //}

                    // These settings are only effective on servers with disabled checking profiles.
                    //defaultCheckSettings: {
                    //  'language': 'en',
                    //  'ruleSetName': 'Plain English',
                    //  'termSets': ['Medical'],
                    //  'checkSpelling': true,
                    //  'checkGrammar': true,
                    //  'checkStyle': true,
                    //  'checkReuse': false,
                    //  'harvestTerms': false,
                    //  'checkSeo': false,
                    //  'termStatuses': ['TERMINOLOGY_DEPRECATED']
                    //}

                });
            }

            console.log('Install acrolinxPlugin in sidebar.');
            sidebarContentWindow.acrolinxPlugin = {

                requestInit: function () {
                    console.log('requestInit');
                    if (config.sidebarType === 'CLOUD') {
                        initSidebarCloud();
                    } else {
                        initSidebarOnPremise();
                    }
                },

                onInitFinished: function (initFinishedResult) {
                    console.log('onInitFinished: ', initFinishedResult);
                    if (initFinishedResult.error) {
                        window.alert(initFinishedResult.error.message);
                    }
                },

                configure: function (configuration) {
                    console.log('configure: ', configuration);
                },

                requestAccessToken: function () {
                    var requestAccessTokenCallback = config.requestAccessTokenCallback;
                    if (requestAccessTokenCallback) {
                        requestAccessTokenCallback(function (accessToken) {
                            sidebarContentWindow.acrolinxSidebar.setAccessToken(accessToken);
                        });
                    }
                },

                requestGlobalCheckSync: function (html, format, documentReference) {
                    if (html.hasOwnProperty("error")) {
                        window.alert(html.error);
                    } else {
                        var checkInfo = sidebarContentWindow.acrolinxSidebar.checkGlobal(html.html, {
                            inputFormat: format || 'HTML',
                            requestDescription: {
                                documentReference: documentReference || 'filename.html'
                            }
                        });
                        adapter.registerCheckCall(checkInfo);
                    }

                },

                requestGlobalCheck: function () {
                    console.log('requestGlobalCheck');
                    var pHtml = adapter.extractHTMLForCheck();
                    var pFormat = adapter.getFormat ? adapter.getFormat() : null;
                    var pDocumentReference = adapter.getDocumentReference ? adapter.getDocumentReference() : null;
                    if (pHtml.then !== undefined) {
                        var self = this;
                        pHtml.then(function (html) {
                            self.requestGlobalCheckSync(html, pFormat, pDocumentReference);
                        });
                    } else {
                        this.requestGlobalCheckSync(pHtml, pFormat, pDocumentReference);

                    }
                },

                onCheckResult: function (checkResult) {
                    return adapter.registerCheckResult(checkResult);
                },

                selectRanges: function (checkId, matches) {
                    console.log('selectRanges: ', checkId, matches);
                    adapter.selectRanges(checkId, matches);

                },

                replaceRanges: function (checkId, matchesWithReplacement) {
                    console.log('replaceRanges: ', checkId, matchesWithReplacement);
                    adapter.replaceRanges(checkId, matchesWithReplacement);

                },

                // only needed for local checks
                getRangesOrder: function (checkedDocumentRanges) {
                    console.log('getRangesOrder: ', checkedDocumentRanges);
                    return [];
                },

                download: function (download) {
                    console.log('download: ', download.url, download);
                    window.open(download.url);
                },

                // only needed for local checks
                verifyRanges: function (checkedDocumentParts) {
                    console.log('verifyRanges: ', checkedDocumentParts);
                    return [];
                },

                disposeCheck: function (checkId) {
                    console.log('disposeCheck: ', checkId);
                }
            };

        }

        function loadSidebarIntoIFrame() {
            var sidebarBaseUrl = config.sidebarType === 'CLOUD' ?
                'https://acrolinx-integrations.acrolinx-cloud.com/sidebar/v13/' :
                'https://acrolinx-sidebar-classic.s3.amazonaws.com/v13/prod/';
            return $.ajax({
                url: sidebarBaseUrl + 'index.html'
            }).then(function (sidebarHtml) {
                var sidebarHtmlWithAbsoluteLinks = sidebarHtml
                    .replace(/src="/g, 'src="' + sidebarBaseUrl)
                    .replace(/href="/g, 'href="' + sidebarBaseUrl);
                sidebarContentWindow.document.open();
                sidebarContentWindow.document.write(sidebarHtmlWithAbsoluteLinks);
                sidebarContentWindow.document.close();
                onSidebarLoaded();
            });
        }

        loadSidebarIntoIFrame();
    }

    var cls = function (conf) {
        this.config = conf;
    };

    cls.prototype = {

        registerAdapter: function (adapter) {
            this.adapter = adapter;
        },

        init: function () {
            initAcrolinxSamplePlugin(this.config, this.adapter);
        }
    };

    return cls;

})();<|endoftext|>


<commit_before>'use strict';

var d        = require('es5-ext/lib/Object/descriptor')
  , DOMInput = require('../date-time').DOMInput

  , DateType = require('dbjs/lib/objects')._get('Date')
  , Input;

require('../');

Input = function (document, ns/*, options*/) {
	DOMInput.call(this, document, ns, arguments[2]);
	this.dom.setAttribute('type', 'date');
	if (ns.max) this.castAttribute('max', ns.max);
	if (ns.min) this.castAttribute('min', ns.min);
	if (ns.step) this.dom.setAttribute('step', ns.step);
	this.dom.addEventListener('input', this.onchange.bind(this), false);
};

Input.prototype = Object.create(DOMInput.prototype, {
	constructor: d(Input),
	_dateToInputValue: d(function (date) {
		return date.toISOString().slice(0, 10);
	})
});

module.exports = Object.defineProperties(DateType, {
	DOMInput: d(Input),
});
<commit_msg>Fix time zone shift issue, related to Date fields<commit_after>'use strict';

var d        = require('es5-ext/lib/Object/descriptor')
  , DOMInput = require('../date-time').DOMInput

  , DateType = require('dbjs/lib/objects')._get('Date')
  , setValue = Object.getOwnPropertyDescriptor(DOMInput.prototype, 'value').set
  , re = /^(\d{4})-(\d{2})-(\d{2})/
  , Input;

require('../');

Input = function (document, ns/*, options*/) {
	DOMInput.call(this, document, ns, arguments[2]);
	this.dom.setAttribute('type', 'date');
	if (ns.max) this.castAttribute('max', ns.max);
	if (ns.min) this.castAttribute('min', ns.min);
	if (ns.step) this.dom.setAttribute('step', ns.step);
	this.dom.addEventListener('input', this.onchange.bind(this), false);
};

Input.prototype = Object.create(DOMInput.prototype, {
	constructor: d(Input),
	_dateToInputValue: d(function (date) {
		return date.toISOString().slice(0, 10);
	}),
	value: d.gs(function () {
		var value = this.dom.value, match;
		if (!value) return null;
		match = String(value).match(re);
		if (!match) return null;
		value = this.ns.normalize(new Date(Number(match[1]), Number(match[2]) - 1,
			Number(match[3]), 12));
		if (this._value && (value.valueOf() === this._value.valueOf())) {
			return this._value;
		}
		return value;
	}, setValue)
});

module.exports = Object.defineProperties(DateType, {
	DOMInput: d(Input),
});
<|endoftext|>


<commit_before>/*
*/

var express = require('express');

var require_loader = require('require_loader');

var appsPath = argv.appsPath;

/*
* Must pass an asbolute path. e.g __dirname + aPath , /home/ubuntu/server/apps
*/
module.exports.setAppsPath = function(aPath) {
    appsPath = aPath;
}

/*
* a function to take the express server.. and append apps to it later
*/
var server = false;
module.exports.load = function(inputServer) {
    server = inputServer;
}<commit_msg>Add the addFullDomain functiln...<commit_after>/*
*/

var express = require('express');

var require_loader = require('require_loader');

var settings = {};
var normalizedDomainList = [];
module.exports.normalizedDomainList = normalizedDomainList;

/*
* Add subodmain function
*/
var addFullDomain = function(fullDomainName, fullName, app)  {
    var canAdd = true;
    for (var i=0; i<normalizedDomainList.length;i++) {
            if (normalizedDomainList[i].name == fullDomainName) {
                    canAdd = false;
                    break;
            }
    }
    if (canAdd) {
            server.use(express.vhost(fullDomainName, app));
            normalizedDomainList.push({name:fullDomainName, fullName:fullName});
    }
}

/*
* a function to take the express server.. and append apps to it later
*/
var server = false;
module.exports.load = function(options) {
    settings = {
        appsPath    :   options.appsPath || false,  /* the folder path where it is beign watch */
        server      :   options.server  || false,   /* the express server / app object */
    }

    if (settings.appsPath !== false && settings.server !== false) {
        // bind util function to the server object first
        settings.server.addFullDomain = addFullDomain;
    } else {
        // error.
    }
}<|endoftext|>


<commit_before>// We used SpiderMonkey documentation and `esprima-fb's` code for references
//   https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API
//   https://github.com/facebook/esprima/blob/7001.0001.0000-dev-harmony-fb/esprima.js#L127-L212
module.exports = {
  // https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API#Functions
  "lexical": [
    "FunctionDeclaration", // function a() {}
    "FunctionExpression", // var a = function () {}
    // DEV: In `esprima-fb`, `ArrowExpression` is `ArrowFunctionExpression`
    "ArrowFunctionExpression" // var a = () =>
  ],
  // https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API#Statements
  "block": [
    "BlockStatement", // { /* code goes here */ }
    "ForStatement", // for (let i = 0; i < 10; i++) ;
    "ForInStatement", // for (let key in obj) ;
    "ForOfStatement", // for (let val in arr) ;
    // DEV: We aren't sure that this is `block` scope but we aren't sure what to call it...
    "ComprehensionBlock" // [val for (val of arr)]
  ]
};

<commit_msg>Moved to data driven content<commit_after>// Load in dependencies
var esprima = require('esprima-fb');

// We used SpiderMonkey documentation and `esprima-fb's` code for references
//   https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API
//   https://github.com/facebook/esprima/blob/7001.0001.0000-dev-harmony-fb/esprima.js#L127-L212
module.exports = {
  // https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API#Functions
  lexical: [
    esprima.Syntax.FunctionDeclaration, // function a() {}
    esprima.Syntax.FunctionExpression, // var a = function () {}
    // DEV: In `esprima-fb`, `ArrowExpression` is `ArrowFunctionExpression`
    esprima.Syntax.ArrowFunctionExpression // var a = () =>
  ],
  // https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API#Statements
  block: [
    esprima.Syntax.BlockStatement, // { /* code goes here */ }
    esprima.Syntax.ForStatement, // for (let i = 0; i < 10; i++) ;
    esprima.Syntax.ForInStatement, // for (let key in obj) ;
    esprima.Syntax.ForOfStatement, // for (let val in arr) ;
    // DEV: We aren't sure that this is `block` scope but we aren't sure what to call it...
    esprima.Syntax.ComprehensionBlock // [val for (val of arr)]
  ]
};

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011-2014 Gary Kramlich <grim@reaperworld.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
var GPlugin = imports.gi.GPlugin;

function gplugin_query() {
	return new GPlugin.PluginInfo({
		id: "gplugin/seed-basic-plugin",
		abi_version: 0x01020304,
		name: "basic plugin",
		authors: ['author1'],
		category: 'test',
		version: 'version',
		license_id: 'license',
		summary: 'summary',
		website: 'website',
		description: 'description'
	});
};

function gplugin_load(plugin) {
	return true;
};

function gplugin_unload(plugin) {
	return false;
};

<commit_msg>Fixed the basic.js plugin to return TRUE on unload.  With the other previous commit, we now pass all of the seed unit tests<commit_after>/*
 * Copyright (C) 2011-2014 Gary Kramlich <grim@reaperworld.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
var GPlugin = imports.gi.GPlugin;

function gplugin_query() {
	return new GPlugin.PluginInfo({
		id: "gplugin/seed-basic-plugin",
		abi_version: 0x01020304,
		name: "basic plugin",
		authors: ['author1'],
		category: 'test',
		version: 'version',
		license_id: 'license',
		summary: 'summary',
		website: 'website',
		description: 'description'
	});
};

function gplugin_load(plugin) {
	return true;
};

function gplugin_unload(plugin) {
	return true;
};

<|endoftext|>


<commit_before>import webpack from 'webpack';
import { resolve } from 'path';
import { existsSync } from 'fs';
import merge from 'webpack-merge';
import { filter } from 'minimatch';
import CopyWebpackPlugin from 'copy-webpack-plugin';
import SWPrecacheWebpackPlugin from 'sw-precache-webpack-plugin';
import RenderHTMLPlugin from './render-html-plugin';
import PushManifestPlugin from './push-manifest';
import baseConfig from './webpack-base-config';
import { normalizePath } from '../../util';

const cleanFilename = name => name.replace(/(^\/(routes|components\/(routes|async))\/|(\/index)?\.js$)/g, '');

function clientConfig(env) {
	const { isProd, source, src /*, port? */ } = env;

	let entry = {
		bundle: resolve(__dirname, './../entry'),
		polyfills: resolve(__dirname, './polyfills')
	};

	if (!isProd) {
		entry.bundle = [
			entry.bundle,
			'webpack-dev-server/client',
			'webpack/hot/dev-server'
		];
	}

	return {
		entry: entry,
		output: {
			path: env.dest,
			publicPath: '/',
			filename: isProd ? '[name].[chunkhash:5].js' : '[name].js',
			chunkFilename: '[name].chunk.[chunkhash:5].js'
		},

		resolveLoader: {
			alias: {
				async: resolve(__dirname, './async-component-loader')
			}
		},

		// automatic async components :)
		module: {
			loaders: [
				{
					test: /\.jsx?$/,
					include: [
						filter(source('routes')+'/{*.js,*/index.js}'),
						filter(source('components')+'/{routes,async}/{*.js,*/index.js}')
					],
					loader: resolve(__dirname, './async-component-loader'),
					options: {
						name(filename) {
							filename = normalizePath(filename);
							let relative = filename.replace(normalizePath(src), '');
							if (!relative.includes('/routes/')) return false;
							return 'route-' + cleanFilename(relative);
						},
						formatName(filename) {
							filename = normalizePath(filename);
							let relative = filename.replace(normalizePath(source('.')), '');
							return cleanFilename(relative);
						}
					}
				}
			]
		},

		plugins: [
			...RenderHTMLPlugin(env),
			new PushManifestPlugin(),
			new CopyWebpackPlugin([
				...(
					existsSync(source('manifest.json'))
					? [{ from:'manifest.json' }]
					: [{
						from: resolve(__dirname, '../../resources/manifest.json'),
						to: 'manifest.json'
					}, {
						from: resolve(__dirname, '../../resources/icon.png'),
						to: 'assets/icon.png'
					}]
				),
				// copy any static files
				existsSync(source('assets')) && { from:'assets', to:'assets' }
			].filter(Boolean))
		]
	};
}

function isProd(config) {
	let limit = 200 * 1000; // 200kb

	const prodConfig = {
		performance: {
			hints: 'warning',
			maxAssetSize: limit,
			maxEntrypointSize: limit,
			...config.pkg.performance
		},

		plugins: [
			new webpack.optimize.UglifyJsPlugin({
				output: { comments:false },
				mangle: true,
				sourceMap: true,
				compress: {
					properties: true,
					keep_fargs: false,
					pure_getters: true,
					collapse_vars: true,
					warnings: false,
					screw_ie8: true,
					sequences: true,
					dead_code: true,
					drop_debugger: true,
					comparisons: true,
					conditionals: true,
					evaluate: true,
					booleans: true,
					loops: true,
					unused: true,
					hoist_funs: true,
					if_return: true,
					join_vars: true,
					cascade: true,
					drop_console: false,
					pure_funcs: [
						'classCallCheck',
						'_classCallCheck',
						'_possibleConstructorReturn',
						'Object.freeze',
						'invariant',
						'warning'
					]
				}
			}),
			new webpack.DefinePlugin({
				'process.env.ADD_SW': config.serviceWorker
			}),
		]
	};

	if (config.serviceWorker) {
		prodConfig.plugins.push(
			new SWPrecacheWebpackPlugin({
				filename: 'sw.js',
				navigateFallback: 'index.html',
				navigateFallbackWhitelist: [/^(?!\/__).*/],
				minify: true,
				stripPrefix: config.cwd,
				staticFileGlobsIgnorePatterns: [
					/polyfills(\..*)?\.js$/,
					/\.map$/,
					/push-manifest\.json$/,
					/.DS_Store/,
					/\.git/
				]
			}),
		);
	}

	return prodConfig;
}

function isDev(config) {
	const { cwd, src } = config;

	return {
		plugins: [
			new webpack.NamedModulesPlugin(),
			new webpack.HotModuleReplacementPlugin()
		],

		devServer: {
			inline: true,
			hot:true,
			compress: true,
			publicPath: '/',
			contentBase: src,
			https: config.https,
			port: process.env.PORT || config.port || 8080,
			host: process.env.HOST || config.host || '0.0.0.0',
			// setup(app) {
			// 	app.use(middleware);
			// },
			disableHostCheck: true,
			historyApiFallback: true,
			quiet: true,
			clientLogLevel: 'none',
			overlay: false,
			stats: 'minimal',
			watchOptions: {
				ignored: [
					resolve(cwd, 'build'),
					resolve(cwd, 'node_modules')
				]
			}
		}
	};
}

export default function (env) {
	return merge(
		baseConfig(env),
		clientConfig(env),
		(env.isProd ? isProd : isDev)(env)
	);
}
<commit_msg>[SW] Don't invoke skipWaiting<commit_after>import webpack from 'webpack';
import { resolve } from 'path';
import { existsSync } from 'fs';
import merge from 'webpack-merge';
import { filter } from 'minimatch';
import CopyWebpackPlugin from 'copy-webpack-plugin';
import SWPrecacheWebpackPlugin from 'sw-precache-webpack-plugin';
import RenderHTMLPlugin from './render-html-plugin';
import PushManifestPlugin from './push-manifest';
import baseConfig from './webpack-base-config';
import { normalizePath } from '../../util';

const cleanFilename = name => name.replace(/(^\/(routes|components\/(routes|async))\/|(\/index)?\.js$)/g, '');

function clientConfig(env) {
	const { isProd, source, src /*, port? */ } = env;

	let entry = {
		bundle: resolve(__dirname, './../entry'),
		polyfills: resolve(__dirname, './polyfills')
	};

	if (!isProd) {
		entry.bundle = [
			entry.bundle,
			'webpack-dev-server/client',
			'webpack/hot/dev-server'
		];
	}

	return {
		entry: entry,
		output: {
			path: env.dest,
			publicPath: '/',
			filename: isProd ? '[name].[chunkhash:5].js' : '[name].js',
			chunkFilename: '[name].chunk.[chunkhash:5].js'
		},

		resolveLoader: {
			alias: {
				async: resolve(__dirname, './async-component-loader')
			}
		},

		// automatic async components :)
		module: {
			loaders: [
				{
					test: /\.jsx?$/,
					include: [
						filter(source('routes')+'/{*.js,*/index.js}'),
						filter(source('components')+'/{routes,async}/{*.js,*/index.js}')
					],
					loader: resolve(__dirname, './async-component-loader'),
					options: {
						name(filename) {
							filename = normalizePath(filename);
							let relative = filename.replace(normalizePath(src), '');
							if (!relative.includes('/routes/')) return false;
							return 'route-' + cleanFilename(relative);
						},
						formatName(filename) {
							filename = normalizePath(filename);
							let relative = filename.replace(normalizePath(source('.')), '');
							return cleanFilename(relative);
						}
					}
				}
			]
		},

		plugins: [
			...RenderHTMLPlugin(env),
			new PushManifestPlugin(),
			new CopyWebpackPlugin([
				...(
					existsSync(source('manifest.json'))
					? [{ from:'manifest.json' }]
					: [{
						from: resolve(__dirname, '../../resources/manifest.json'),
						to: 'manifest.json'
					}, {
						from: resolve(__dirname, '../../resources/icon.png'),
						to: 'assets/icon.png'
					}]
				),
				// copy any static files
				existsSync(source('assets')) && { from:'assets', to:'assets' }
			].filter(Boolean))
		]
	};
}

function isProd(config) {
	let limit = 200 * 1000; // 200kb

	const prodConfig = {
		performance: {
			hints: 'warning',
			maxAssetSize: limit,
			maxEntrypointSize: limit,
			...config.pkg.performance
		},

		plugins: [
			new webpack.optimize.UglifyJsPlugin({
				output: { comments:false },
				mangle: true,
				sourceMap: true,
				compress: {
					properties: true,
					keep_fargs: false,
					pure_getters: true,
					collapse_vars: true,
					warnings: false,
					screw_ie8: true,
					sequences: true,
					dead_code: true,
					drop_debugger: true,
					comparisons: true,
					conditionals: true,
					evaluate: true,
					booleans: true,
					loops: true,
					unused: true,
					hoist_funs: true,
					if_return: true,
					join_vars: true,
					cascade: true,
					drop_console: false,
					pure_funcs: [
						'classCallCheck',
						'_classCallCheck',
						'_possibleConstructorReturn',
						'Object.freeze',
						'invariant',
						'warning'
					]
				}
			}),
			new webpack.DefinePlugin({
				'process.env.ADD_SW': config.serviceWorker
			}),
		]
	};

	if (config.serviceWorker) {
		prodConfig.plugins.push(
			new SWPrecacheWebpackPlugin({
				filename: 'sw.js',
				navigateFallback: 'index.html',
				navigateFallbackWhitelist: [/^(?!\/__).*/],
				minify: true,
				skipWaiting: false,
				stripPrefix: config.cwd,
				staticFileGlobsIgnorePatterns: [
					/polyfills(\..*)?\.js$/,
					/\.map$/,
					/push-manifest\.json$/,
					/.DS_Store/,
					/\.git/
				]
			}),
		);
	}

	return prodConfig;
}

function isDev(config) {
	const { cwd, src } = config;

	return {
		plugins: [
			new webpack.NamedModulesPlugin(),
			new webpack.HotModuleReplacementPlugin()
		],

		devServer: {
			inline: true,
			hot:true,
			compress: true,
			publicPath: '/',
			contentBase: src,
			https: config.https,
			port: process.env.PORT || config.port || 8080,
			host: process.env.HOST || config.host || '0.0.0.0',
			// setup(app) {
			// 	app.use(middleware);
			// },
			disableHostCheck: true,
			historyApiFallback: true,
			quiet: true,
			clientLogLevel: 'none',
			overlay: false,
			stats: 'minimal',
			watchOptions: {
				ignored: [
					resolve(cwd, 'build'),
					resolve(cwd, 'node_modules')
				]
			}
		}
	};
}

export default function (env) {
	return merge(
		baseConfig(env),
		clientConfig(env),
		(env.isProd ? isProd : isDev)(env)
	);
}
<|endoftext|>


<commit_before>/**
 * This method enhances a base object which would normally contain data, with
 * methods from another object that might work on manipulating that data.
 * All the added methods are set as non enumerable, non configurable, and non
 * writable properties. This ensures that if we try to clone or stringify the
 * base object, we don't have to worry about these additional methods.
 * @private
 * @param {object} baseObject - Base object with data
 * @param {object} methodsObject - Object with methods as properties. The key
 * values used here will be the same that will be defined on the baseObject.
 */
export default function enhanceWithMethods (baseObject, methodsObject) {
  return Object.keys(methodsObject).reduce((enhancedObject, methodName) => {
    Object.defineProperty(enhancedObject, methodName, {
      enumerable: false,
      configurable: false,
      writable: false,
      value: methodsObject[methodName]
    })
    return enhancedObject
  }, baseObject)
}
<commit_msg>fix: allow methods to be configurable (#317)<commit_after>/**
 * This method enhances a base object which would normally contain data, with
 * methods from another object that might work on manipulating that data.
 * All the added methods are set as non enumerable, non configurable, and non
 * writable properties. This ensures that if we try to clone or stringify the
 * base object, we don't have to worry about these additional methods.
 * @private
 * @param {object} baseObject - Base object with data
 * @param {object} methodsObject - Object with methods as properties. The key
 * values used here will be the same that will be defined on the baseObject.
 */
export default function enhanceWithMethods (baseObject, methodsObject) {
  return Object.keys(methodsObject).reduce((enhancedObject, methodName) => {
    Object.defineProperty(enhancedObject, methodName, {
      enumerable: false,
      configurable: true,
      writable: false,
      value: methodsObject[methodName]
    })
    return enhancedObject
  }, baseObject)
}
<|endoftext|>


<commit_before>var path = require('path')
// path.isAbsolute shim for Node.js 0.10 support
var fs = require('graceful-fs')

/**
 * Function that returns two types of paths, one relative to symlink, and one
 * relative to the current working directory. Checks if path is absolute or
 * relative. If the path is relative, this function checks if the path is
 * relative to symlink or relative to current working directory. This is an
 * initiative to find a smarter `srcpath` to supply when building symlinks.
 * This allows you to determine which path to use out of one of three possible
 * types of source paths. The first is an absolute path. This is detected by
 * `path.isAbsolute()`. When an absolute path is provided, it is checked to
 * see if it exists. If it does it's used, if not an error is returned
 * (callback)/ thrown (sync). The other two options for `srcpath` are a
 * relative url. By default Node's `fs.symlink` works by creating a symlink
 * using `dstpath` and expects the `srcpath` to be relative to the newly
 * created symlink. If you provide a `srcpath` that does not exist on the file
 * system it results in a broken symlink. To minimize this, the function
 * checks to see if the 'relative to symlink' source file exists, and if it
 * does it will use it. If it does not, it checks if there's a file that
 * exists that is relative to the current working directory, if does its used.
 * This preserves the expectations of the original fs.symlink spec and adds
 * the ability to pass in `relative to current working direcotry` paths.
 */

function symlinkPaths (srcpath, dstpath, callback) {
  if (path.isAbsolute(srcpath)) {
    return fs.lstat(srcpath, function (err, stat) {
      if (err) {
        err.message = err.message.replace('lstat', 'ensureSymlink')
        return callback(err)
      }
      return callback(null, {
        'toCwd': srcpath,
        'toDst': srcpath
      })
    })
  } else {
    var dstdir = path.dirname(dstpath)
    var relativeToDst = path.join(dstdir, srcpath)
    return fs.exists(relativeToDst, function (exists) {
      if (exists) {
        return callback(null, {
          'toCwd': relativeToDst,
          'toDst': srcpath
        })
      } else {
        return fs.lstat(srcpath, function (err, stat) {
          if (err) {
            err.message = err.message.replace('lstat', 'ensureSymlink')
            return callback(err)
          }
          return callback(null, {
            'toCwd': srcpath,
            'toDst': path.relative(dstdir, srcpath)
          })
        })
      }
    })
  }
}

function symlinkPathsSync (srcpath, dstpath) {
  var exists
  if (path.isAbsolute(srcpath)) {
    exists = fs.existsSync(srcpath)
    if (!exists) throw new Error('absolute srcpath does not exist')
    return {
      'toCwd': srcpath,
      'toDst': srcpath
    }
  } else {
    var dstdir = path.dirname(dstpath)
    var relativeToDst = path.join(dstdir, srcpath)
    exists = fs.existsSync(relativeToDst)
    if (exists) {
      return {
        'toCwd': relativeToDst,
        'toDst': srcpath
      }
    } else {
      exists = fs.existsSync(srcpath)
      if (!exists) throw new Error('relative srcpath does not exist')
      return {
        'toCwd': srcpath,
        'toDst': path.relative(dstdir, srcpath)
      }
    }
  }
}

module.exports = {
  'symlinkPaths': symlinkPaths,
  'symlinkPathsSync': symlinkPathsSync
}
<commit_msg>Refactor symlinkPaths/Sync<commit_after>'use strict'

const path = require('path')
// path.isAbsolute shim for Node.js 0.10 support
const fs = require('graceful-fs')

/**
 * Function that returns two types of paths, one relative to symlink, and one
 * relative to the current working directory. Checks if path is absolute or
 * relative. If the path is relative, this function checks if the path is
 * relative to symlink or relative to current working directory. This is an
 * initiative to find a smarter `srcpath` to supply when building symlinks.
 * This allows you to determine which path to use out of one of three possible
 * types of source paths. The first is an absolute path. This is detected by
 * `path.isAbsolute()`. When an absolute path is provided, it is checked to
 * see if it exists. If it does it's used, if not an error is returned
 * (callback)/ thrown (sync). The other two options for `srcpath` are a
 * relative url. By default Node's `fs.symlink` works by creating a symlink
 * using `dstpath` and expects the `srcpath` to be relative to the newly
 * created symlink. If you provide a `srcpath` that does not exist on the file
 * system it results in a broken symlink. To minimize this, the function
 * checks to see if the 'relative to symlink' source file exists, and if it
 * does it will use it. If it does not, it checks if there's a file that
 * exists that is relative to the current working directory, if does its used.
 * This preserves the expectations of the original fs.symlink spec and adds
 * the ability to pass in `relative to current working direcotry` paths.
 */

function symlinkPaths (srcpath, dstpath, callback) {
  if (path.isAbsolute(srcpath)) {
    return fs.lstat(srcpath, (err, stat) => {
      if (err) {
        err.message = err.message.replace('lstat', 'ensureSymlink')
        return callback(err)
      }
      return callback(null, {
        'toCwd': srcpath,
        'toDst': srcpath
      })
    })
  } else {
    const dstdir = path.dirname(dstpath)
    const relativeToDst = path.join(dstdir, srcpath)
    return fs.exists(relativeToDst, exists => {
      if (exists) {
        return callback(null, {
          'toCwd': relativeToDst,
          'toDst': srcpath
        })
      } else {
        return fs.lstat(srcpath, (err, stat) => {
          if (err) {
            err.message = err.message.replace('lstat', 'ensureSymlink')
            return callback(err)
          }
          return callback(null, {
            'toCwd': srcpath,
            'toDst': path.relative(dstdir, srcpath)
          })
        })
      }
    })
  }
}

function symlinkPathsSync (srcpath, dstpath) {
  let exists
  if (path.isAbsolute(srcpath)) {
    exists = fs.existsSync(srcpath)
    if (!exists) throw new Error('absolute srcpath does not exist')
    return {
      'toCwd': srcpath,
      'toDst': srcpath
    }
  } else {
    const dstdir = path.dirname(dstpath)
    const relativeToDst = path.join(dstdir, srcpath)
    exists = fs.existsSync(relativeToDst)
    if (exists) {
      return {
        'toCwd': relativeToDst,
        'toDst': srcpath
      }
    } else {
      exists = fs.existsSync(srcpath)
      if (!exists) throw new Error('relative srcpath does not exist')
      return {
        'toCwd': srcpath,
        'toDst': path.relative(dstdir, srcpath)
      }
    }
  }
}

module.exports = {
  symlinkPaths,
  symlinkPathsSync
}
<|endoftext|>


<commit_before>/*global self*/
import Promise from './promise';

export default function polyfill() {
  var local = (typeof global !== 'undefined') ? global : self;
  var P = local.Promise;

  if (P && Object.prototype.toString.call(Promise.resolve()) === '[object Promise]' && !Promise.cast) {
    try {
      var K = function (r) { P.call(this, r); }
      K.prototype = Object.create(P.prototype);
      new K(function() { })
      return;
    } catch(e) {
      // Promise is not subclassable
    }
  }

  local.Promise = Promise;
}
<commit_msg>Add support of polyfill() for some more environments<commit_after>/*global self*/
import Promise from './promise';

export default function polyfill() {
  var local;

  if (typeof global !== 'undefined') {
      local = global;
  } else if (typeof self !== 'undefined') {
      local = self;
  } else {
      try {
          local = Function('return this')();
      } catch (e) {
          throw new Error('polyfill failed because global object is unavailable in this environment');
      }
  }

  var P = local.Promise;

  if (P && Object.prototype.toString.call(Promise.resolve()) === '[object Promise]' && !Promise.cast) {
    try {
      var K = function (r) { P.call(this, r); }
      K.prototype = Object.create(P.prototype);
      new K(function() { })
      return;
    } catch(e) {
      // Promise is not subclassable
    }
  }

  local.Promise = Promise;
}
<|endoftext|>