<commit_before>// Handler when the DOM is fully loaded
document.addEventListener("DOMContentLoaded", function(){

    // Handle form submission
    if (window.location.hash === '#done') {
        for (let i = 0; i < 2; i++) {
            document.querySelectorAll('.notice-msg')[i].classList.remove('invisible');
            document.getElementsByTagName('form')[i].classList.add('invisible');
        }
        if(window.history.pushState) {
            window.history.pushState('', '/', window.location.pathname)
        } else {
            window.location.hash = '';
        }
        let navbarHeight = checkWidth();
        const to = document.getElementById('coming-soon').offsetTop - navbarHeight;
        scrollTo(document.body, to, 1000);
    }

    // Toggle mobile menu
    const toggleButton = document.getElementById('toggle-menu');
    const navbar = document.getElementsByClassName('navbar-fixed-top')[0];
    toggleButton.addEventListener('click', function (e) {
        if (navbar.classList.contains('expand')) {
            navbar.classList.remove('expand');
        } else {
            navbar.classList.add('expand');
        }
        e.stopPropagation();
    });

    // Scroll to section
    document.addEventListener('click', function(e) {
        if (e.target.classList.contains('page-scroll')) {
            document.getElementById('home').classList.remove('invisible');
            document.getElementById('faq').classList.add('invisible');
            const target = e.target.getAttribute('href').substr(1);
            let offset = 0;
            if (target === 'who-we-are' || target === 'page-top') {
                offset = 55;
            }
            let navbarHeight = checkWidth();
            const to = document.getElementById(target).offsetTop - navbarHeight - offset;
            scrollTo(document.body, to, 1000);
            e.preventDefault();
        }
    });

    const faqButton = document.getElementById('faq-btn');
    faqButton.addEventListener('click', function(e) {
        document.getElementById('faq').classList.remove('invisible');
        scrollTo(document.body, 0, 1000);
        e.stopPropagation();
        document.getElementById('home').classList.add('invisible');
    });

    window.onresize = checkWidth;
    window.onscroll = collapseNavbar;
    document.ready = collapseNavbar;
});

// Collapse navbar on scroll
function collapseNavbar() {
    const navbarFixedTopEl = document.getElementsByClassName('navbar-fixed-top');
    if (window.scrollY > 50) {
        navbarFixedTopEl[0].classList.add('top-nav-collapse');
    } else {
        navbarFixedTopEl[0].classList.remove('top-nav-collapse');
    }
}

// Check view width, add navbar height as offset if on desktop
function checkWidth() {
    let mq = window.matchMedia("(max-width: 1199px)");
    if (mq.matches) {
        return 0;
    } else {
        return document.getElementsByClassName('navbar-fixed-top')[0].scrollHeight;
    }
}

function checkBrowser() {
    const isFirefox = typeof InstallTrigger !== 'undefined';   // Firefox 1.0+
    const isIE = /*@cc_on!@*/false || !!document.documentMode; // Internet Explorer 6-11

    if (isFirefox || isIE) {
        return true;
    } else {
        return false;
    }
}

// scrollTo function with animation
// - Gist reference: https://gist.github.com/andjosh/6764939
function scrollTo(element, to, duration) {
    if (checkBrowser()) {
        element = document.documentElement;
    }
    let start = element.scrollTop,
        change = to - start,
        currentTime = 0,
        increment = 20;

    const animateScroll = function(){
        currentTime += increment;
        let val = Math.easeInOutQuad(currentTime, start, change, duration);
        element.scrollTop = val;
        if(currentTime < duration) {
            setTimeout(animateScroll, increment);
        }
    };
    animateScroll();
}

//t = current time
//b = start value
//c = change in value
//d = duration
Math.easeInOutQuad = function (t, b, c, d) {
    t /= d/2;
    if (t < 1) return c/2*t*t + b;
    t--;
    return -c/2 * (t*(t-2) - 1) + b;
};<commit_msg>Add GTM script<commit_after>// Handler when the DOM is fully loaded
document.addEventListener("DOMContentLoaded", function(){
    dataLayer.push({ event: 'page_load'});

    // Handle form submission
    if (window.location.hash === '#done') {
        for (let i = 0; i < 2; i++) {
            document.querySelectorAll('.notice-msg')[i].classList.remove('invisible');
            document.getElementsByTagName('form')[i].classList.add('invisible');
        }
        if(window.history.pushState) {
            window.history.pushState('', '/', window.location.pathname)
        } else {
            window.location.hash = '';
        }
        let navbarHeight = checkWidth();
        const to = document.getElementById('coming-soon').offsetTop - navbarHeight;
        scrollTo(document.body, to, 1000);
    }

    // Toggle mobile menu
    const toggleButton = document.getElementById('toggle-menu');
    const navbar = document.getElementsByClassName('navbar-fixed-top')[0];
    toggleButton.addEventListener('click', function (e) {
        if (navbar.classList.contains('expand')) {
            navbar.classList.remove('expand');
        } else {
            navbar.classList.add('expand');
        }
        e.stopPropagation();
    });

    // Scroll to section
    document.addEventListener('click', function(e) {
        if (e.target.classList.contains('page-scroll')) {
            document.getElementById('home').classList.remove('invisible');
            document.getElementById('faq').classList.add('invisible');
            const target = e.target.getAttribute('href').substr(1);
            let offset = 0;
            if (target === 'who-we-are' || target === 'page-top') {
                offset = 55;
            }
            let navbarHeight = checkWidth();
            const to = document.getElementById(target).offsetTop - navbarHeight - offset;
            scrollTo(document.body, to, 1000);
            e.preventDefault();
        }
    });

    const faqButton = document.getElementById('faq-btn');
    faqButton.addEventListener('click', function(e) {
        document.getElementById('faq').classList.remove('invisible');
        scrollTo(document.body, 0, 1000);
        e.stopPropagation();
        document.getElementById('home').classList.add('invisible');
    });

    window.onresize = checkWidth;
    window.onscroll = collapseNavbar;
    document.ready = collapseNavbar;
});

// Collapse navbar on scroll
function collapseNavbar() {
    const navbarFixedTopEl = document.getElementsByClassName('navbar-fixed-top');
    if (window.scrollY > 50) {
        navbarFixedTopEl[0].classList.add('top-nav-collapse');
    } else {
        navbarFixedTopEl[0].classList.remove('top-nav-collapse');
    }
}

// Check view width, add navbar height as offset if on desktop
function checkWidth() {
    let mq = window.matchMedia("(max-width: 1199px)");
    if (mq.matches) {
        return 0;
    } else {
        return document.getElementsByClassName('navbar-fixed-top')[0].scrollHeight;
    }
}

function checkBrowser() {
    const isFirefox = typeof InstallTrigger !== 'undefined';   // Firefox 1.0+
    const isIE = /*@cc_on!@*/false || !!document.documentMode; // Internet Explorer 6-11

    if (isFirefox || isIE) {
        return true;
    } else {
        return false;
    }
}

// scrollTo function with animation
// - Gist reference: https://gist.github.com/andjosh/6764939
function scrollTo(element, to, duration) {
    if (checkBrowser()) {
        element = document.documentElement;
    }
    let start = element.scrollTop,
        change = to - start,
        currentTime = 0,
        increment = 20;

    const animateScroll = function(){
        currentTime += increment;
        let val = Math.easeInOutQuad(currentTime, start, change, duration);
        element.scrollTop = val;
        if(currentTime < duration) {
            setTimeout(animateScroll, increment);
        }
    };
    animateScroll();
}

//t = current time
//b = start value
//c = change in value
//d = duration
Math.easeInOutQuad = function (t, b, c, d) {
    t /= d/2;
    if (t < 1) return c/2*t*t + b;
    t--;
    return -c/2 * (t*(t-2) - 1) + b;
};<|endoftext|>


<commit_before>(function($, window, document, undefined) {

    var pluginName = "jqueryVideoLightning",
        defaults = {
            id: "y-dQw4w9WgXcQ",
            width: "640px",
            height: "390px",
            autoplay: 0,
            autohide: 2,
            controls: 1,
            iv_load_policy: 1,
            loop: 0,
            modestbranding: 0,
            playlist: "",
            related: 0,
            showinfo: 1,
            start_time: 0,
            theme: "dark",
            color: "",
            byline: 1,
            portrait: 1,
            effect_in: "fadeIn",
            ease_in: 300,
            ease_out: 0,
            backdrop_color: "#000",
            backdrop_opacity: 1,
            glow: 0,
            glow_color: "#fff"
        };

    function JQVideoLightning ( element, options ) {
        this.element = element;
        this.settings = $.extend( {}, defaults, options );
        this._defaults = defaults;
        this._name = pluginName;
        this.init();
    }

    JQVideoLightning.prototype = {
        init: function () {
            var void_target, void_elements, target, target_class;
            void_elements = [ "AREA", "BASE", "BR", "COL", "COMMAND", "EMBED", "HR", "IMG", "INPUT", "KEYGEN", "LINK", "META", "PARAM", "SOURCE", "TRACK", "WBR" ];
            void_target = 0;
            target_class = ".video-target";

            $(this.element).css( "cursor", "pointer" );

            if (($.inArray($(this.element).prop('tagName'), void_elements)) == -1) {
                target = $(this.element);
                target.addClass("video-target");
            }
            else {
                $("body").append('
' + '
');
                target = $(target_class);
                void_target = 1;
            }

            function callPlayer() {
                $(this.player(target, $(this).settings), void_target);
            }

            $(this.element).on( "click", $.proxy(callPlayer, this));
        },

        player: function ( target, settings, void_target ) {
            var id, video_autohide, video_autoplay, video_byline, video_color, video_controls, video_height, video_id, video_iv_load_policy, video_loop, video_modestbranding, video_playlist, video_portrait, video_related, video_showinfo, video_start_time, video_theme, video_vendor, video_width, vimeo_player, youtube_player, ease_in, glow, glow_color, backdrop_color, backdrop_opacity, red, green, blue, effect_in, display_ratio;

            settings = this.settings;

            if (target.find(".video-wrapper").is(':visible')) {
                target.find(".video").remove();
                target.find(".video-wrapper").hide((settings.easeOut));
                target.find(".video-wrapper").remove();
                if (void_target == 1){target.remove()}
                return $(this).destroy;
            } else {
                id = (typeof target.data("videoId") === 'undefined') ? settings.id : target.data("videoId");
                video_vendor = id.split("-")[0];
                if ((video_vendor === "v") || (video_vendor === "V")) {
                    video_vendor = "Vimeo";
                } else {
                    video_vendor = "Youtube";
                }
                video_id = id.split("-")[1]; // Youtube: "y-XbTtgr8J8uU" Vimeo: "v-32187194"
                video_width = target.data("videoWidth") || settings.width; // Y&V: video width in px
                video_height = target.data("videoHeight") || settings.height; // Y&V: video height in px
                display_ratio = parseInt(video_height) / parseInt(video_width);
                if (parseInt(video_width) > $(document).width() - 20) {
                    video_width = $(document).width() - 20 + "px";
                    video_height = display_ratio * parseInt(video_width) + "px";
                }
                video_autoplay = target.data("videoAutoplay") || settings.autoplay; // Y&V: start playback immediately (0,1)
                video_autohide = target.data("videoAutohide") || settings.autohide; // Y: auto hide controls after video load (0,1,2)
                video_controls = target.data("videoControls") || settings.controls; // Y: display controls (0,1,2)
                video_iv_load_policy = target.data("videoIvLoadPolicy") || settings.iv_load_policy; // Y: display annotations (1,3)
                video_loop = target.data("videoLoop") || settings.loop; // Y&V: loop video playback (0,1)
                video_modestbranding = target.data("videoModestbranding") || settings.modestbranding; // Y: hide large Youtube logo (0,1)
                video_playlist = target.data("videoPlaylist") || settings.playlist; // Y: comma-separated list of video IDs to play
                video_related = target.data("videoRelated") || settings.related; // Y: show related videos when playback id finished (0,1)
                video_showinfo = target.data("videoShowinfo") || settings.showinfo; // Y: display title, uploader (0,1)  V: display title (0,1)
                video_start_time = target.data("videoStartTime") || settings.start_time; // Y: playback start position in seconds (ex. "132" starts at 2mins, 12secs)
                video_theme = target.data("videoTheme") || settings.theme; // Y: player theme ("dark","light")
                if (video_vendor == "Vimeo"){
                    video_color = target.data("videoColor") || prepHex(settings.color); // V: player controls color (hex code minus the "#", default is "00adef")
                } else {
                    video_color = target.data("videoColor") || settings.color; // Y: player controls color ("red","white")
                }
                video_byline = target.data("videoByline") || settings.byline; // V: display byline (0,1)
                video_portrait = target.data("videoPortrait") || settings.portrait; // V: display user's portrait (0,1)
                youtube_player = $("<embed src=\"https://www.youtube.com/embed/" + video_id + "?autoplay=" + video_autoplay + "&autohide=" + video_autohide + "&controls=" + video_controls + "&iv_load_policy=" + video_iv_load_policy + "&loop=" + video_loop + "&modestbranding=" + video_modestbranding + "&playlist=" + video_playlist + "&rel=" + video_related + "&showinfo=" + video_showinfo + "&start=" + video_start_time + "&theme=" + video_theme + "&color=" + video_color + "\" width=\"" + video_width + "\" height=\"" + video_height + "\" frameborder=\"0\" allowfullscreen></embed>");
                vimeo_player = $("");
                effect_in = settings.effect_in;
                ease_in = settings.ease_in;
                glow = settings.glow;
                glow_color = settings.glow_color;
                backdrop_color = settings.backdrop_color;
                backdrop_opacity = settings.backdrop_opacity;

                function colorConverter(hex){
                    red = parseInt((prepHex(hex)).substring(0,2),16);
                    blue = parseInt((prepHex(hex)).substring(2,4),16);
                    green = parseInt((prepHex(hex)).substring(4,6),16);
                    return {
                        red: red,
                        blue: blue,
                        green: green
                    };
                }

                function fullHex(hex){
                    hex = "#" + prepHex(hex);
                    return hex;
                }

                function prepHex(hex){
                    hex = (hex.charAt(0)=="#") ? hex.split("#")[1]:hex;
                    if (hex.length == 3){
                        hex = hex + hex;
                    }
                    return hex;
                }

                target.append('

');
                target.find(".video-wrapper").css({
                    backgroundColor: "rgba(" + colorConverter(backdrop_color).red + "," + colorConverter(backdrop_color).blue + "," + colorConverter(backdrop_color).green + "," + backdrop_opacity + ")"
                });
                target.find(".video-frame").css({
                    width:  video_width,
                    height: video_height,
                    marginTop: '-' + ((video_height.split("p")[0])/2) + 'px',
                    marginLeft: '-' + ((video_width.split("p")[0])/2) + 'px',
                    boxShadow: '0px 0px ' + glow + 'px ' + (glow/5) + 'px ' + fullHex(glow_color)
                });
                target.find(".video-wrapper")[effect_in](ease_in);
                if (video_vendor === "Vimeo") {
                    return target.find(".video").append(vimeo_player);
                } else {
                    return target.find(".video").append(youtube_player);
                }
            }
        },

        destroy: function () {
            $(this).off();
            $(this).removeData();
        }
    };

    $.fn[ pluginName ] = function ( options ) {
        return this.each(function() {
            if ( !$.data( this, "plugin_" + pluginName ) ) {
                $.data( this, "plugin_" + pluginName, new JQVideoLightning( this, options ) );
            }
        });
    };

    return this;

})( jQuery, window, document );<commit_msg>fixes #2 : Firefox compatibility issue<commit_after>(function($, window, document, undefined) {

    var pluginName = "jqueryVideoLightning",
        defaults = {
            id: "y-dQw4w9WgXcQ",
            width: "640px",
            height: "390px",
            autoplay: 0,
            autohide: 2,
            controls: 1,
            iv_load_policy: 1,
            loop: 0,
            modestbranding: 0,
            playlist: "",
            related: 0,
            showinfo: 1,
            start_time: 0,
            theme: "dark",
            color: "",
            byline: 1,
            portrait: 1,
            effect_in: "fadeIn",
            ease_in: 300,
            ease_out: 0,
            backdrop_color: "#000",
            backdrop_opacity: 1,
            glow: 0,
            glow_color: "#fff"
        };

    function JQVideoLightning ( element, options ) {
        this.element = element;
        this.settings = $.extend( {}, defaults, options );
        this._defaults = defaults;
        this._name = pluginName;
        this.init();
    }

    JQVideoLightning.prototype = {
        init: function () {
            var void_target, void_elements, target, target_class;
            void_elements = [ "AREA", "BASE", "BR", "COL", "COMMAND", "EMBED", "HR", "IMG", "INPUT", "KEYGEN", "LINK", "META", "PARAM", "SOURCE", "TRACK", "WBR" ];
            void_target = 0;
            target_class = ".video-target";

            $(this.element).css( "cursor", "pointer" );

            if (($.inArray($(this.element).prop('tagName'), void_elements)) == -1) {
                target = $(this.element);
                target.addClass("video-target");
            }
            else {
                $("body").append('
' + '
');
                target = $(target_class);
                void_target = 1;
            }

            function callPlayer() {
                $(this.player(target, $(this).settings), void_target);
            }

            $(this.element).on( "click", $.proxy(callPlayer, this));
        },

        player: function ( target, settings, void_target ) {
            var id, video_autohide, video_autoplay, video_byline, video_color, video_controls, video_height, video_id, video_iv_load_policy, video_loop, video_modestbranding, video_playlist, video_portrait, video_related, video_showinfo, video_start_time, video_theme, video_vendor, video_width, vimeo_player, youtube_player, ease_in, glow, glow_color, backdrop_color, backdrop_opacity, red, green, blue, effect_in, display_ratio;

            function colorConverter(hex){
                red = parseInt((prepHex(hex)).substring(0,2),16);
                blue = parseInt((prepHex(hex)).substring(2,4),16);
                green = parseInt((prepHex(hex)).substring(4,6),16);
                return {
                    red: red,
                    blue: blue,
                    green: green
                };
            }

            function fullHex(hex){
                hex = "#" + prepHex(hex);
                return hex;
            }

            function prepHex(hex){
                hex = (hex.charAt(0)=="#") ? hex.split("#")[1]:hex;
                if (hex.length == 3){
                    hex = hex + hex;
                }
                return hex;
            }

            settings = this.settings;

            if (target.find(".video-wrapper").is(':visible')) {
                target.find(".video").remove();
                target.find(".video-wrapper").hide((settings.easeOut));
                target.find(".video-wrapper").remove();
                if (void_target == 1){target.remove()}
                return $(this).destroy;
            } else {
                id = (typeof target.data("videoId") === 'undefined') ? settings.id : target.data("videoId");
                video_vendor = id.split("-")[0];
                if ((video_vendor === "v") || (video_vendor === "V")) {
                    video_vendor = "Vimeo";
                } else {
                    video_vendor = "Youtube";
                }
                video_id = id.split("-")[1]; // Youtube: "y-XbTtgr8J8uU" Vimeo: "v-32187194"
                video_width = target.data("videoWidth") || settings.width; // Y&V: video width in px
                video_height = target.data("videoHeight") || settings.height; // Y&V: video height in px
                display_ratio = parseInt(video_height) / parseInt(video_width);
                if (parseInt(video_width) > $(document).width() - 20) {
                    video_width = $(document).width() - 20 + "px";
                    video_height = display_ratio * parseInt(video_width) + "px";
                }
                video_autoplay = target.data("videoAutoplay") || settings.autoplay; // Y&V: start playback immediately (0,1)
                video_autohide = target.data("videoAutohide") || settings.autohide; // Y: auto hide controls after video load (0,1,2)
                video_controls = target.data("videoControls") || settings.controls; // Y: display controls (0,1,2)
                video_iv_load_policy = target.data("videoIvLoadPolicy") || settings.iv_load_policy; // Y: display annotations (1,3)
                video_loop = target.data("videoLoop") || settings.loop; // Y&V: loop video playback (0,1)
                video_modestbranding = target.data("videoModestbranding") || settings.modestbranding; // Y: hide large Youtube logo (0,1)
                video_playlist = target.data("videoPlaylist") || settings.playlist; // Y: comma-separated list of video IDs to play
                video_related = target.data("videoRelated") || settings.related; // Y: show related videos when playback id finished (0,1)
                video_showinfo = target.data("videoShowinfo") || settings.showinfo; // Y: display title, uploader (0,1)  V: display title (0,1)
                video_start_time = target.data("videoStartTime") || settings.start_time; // Y: playback start position in seconds (ex. "132" starts at 2mins, 12secs)
                video_theme = target.data("videoTheme") || settings.theme; // Y: player theme ("dark","light")
                if (video_vendor == "Vimeo"){
                    video_color = target.data("videoColor") || prepHex(settings.color); // V: player controls color (hex code minus the "#", default is "00adef")
                } else {
                    video_color = target.data("videoColor") || settings.color; // Y: player controls color ("red","white")
                }
                video_byline = target.data("videoByline") || settings.byline; // V: display byline (0,1)
                video_portrait = target.data("videoPortrait") || settings.portrait; // V: display user's portrait (0,1)
                youtube_player = $("<iframe src=\"https://www.youtube.com/embed/" + video_id + "?autoplay=" + video_autoplay + "&autohide=" + video_autohide + "&controls=" + video_controls + "&iv_load_policy=" + video_iv_load_policy + "&loop=" + video_loop + "&modestbranding=" + video_modestbranding + "&playlist=" + video_playlist + "&rel=" + video_related + "&showinfo=" + video_showinfo + "&start=" + video_start_time + "&theme=" + video_theme + "&color=" + video_color + "\" width=\"" + video_width + "\" height=\"" + video_height + "\" frameborder=\"0\" allowfullscreen>");
                vimeo_player = $("");
                effect_in = settings.effect_in;
                ease_in = settings.ease_in;
                glow = settings.glow;
                glow_color = settings.glow_color;
                backdrop_color = settings.backdrop_color;
                backdrop_opacity = settings.backdrop_opacity;

                target.append('

');
                target.find(".video-wrapper").css({
                    backgroundColor: "rgba(" + colorConverter(backdrop_color).red + "," + colorConverter(backdrop_color).blue + "," + colorConverter(backdrop_color).green + "," + backdrop_opacity + ")"
                });
                target.find(".video-frame").css({
                    width:  video_width,
                    height: video_height,
                    marginTop: '-' + ((video_height.split("p")[0])/2) + 'px',
                    marginLeft: '-' + ((video_width.split("p")[0])/2) + 'px',
                    boxShadow: '0px 0px ' + glow + 'px ' + (glow/5) + 'px ' + fullHex(glow_color)
                });
                target.find(".video-wrapper")[effect_in](ease_in);
                if (video_vendor === "Vimeo") {
                    return target.find(".video").append(vimeo_player);
                } else {
                    return target.find(".video").append(youtube_player);
                }
            }
        },

        destroy: function () {
            $(this).off();
            $(this).removeData();
        }
    };

    $.fn[ pluginName ] = function ( options ) {
        return this.each(function() {
            if ( !$.data( this, "plugin_" + pluginName ) ) {
                $.data( this, "plugin_" + pluginName, new JQVideoLightning( this, options ) );
            }
        });
    };

    return this;

})( jQuery, window, document );<|endoftext|>


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

/**
 * External dependencies
 */
const { default: iterateJsdoc } = require( 'eslint-plugin-jsdoc/dist/iterateJsdoc' );
const semverCompare = require( 'semver-compare' );
const semverRegex = require( 'semver-regex' );

module.exports = iterateJsdoc( ( {
	context,
	jsdoc,
	jsdocNode,
	utils,
} ) => {
	if ( ! jsdoc.tags || ! jsdoc.tags.length ) {
		return;
	}

	// If the `@ignore` tag is in this JSDoc block, ignore it and don't require a `@since` tag.
	if ( utils.hasTag( 'ignore' ) ) {
		return;
	}

	if ( ! utils.hasTag( 'since' ) ) {
		context.report( {
			data: { name: jsdocNode.name },
			message: `Missing @since tag in JSDoc.`,
			node: jsdocNode,
		} );

		return;
	}

	// Get all @since tags and make sure the format is correct.
	const sinceTags = utils.filterTags( ( { tag } ) => {
		return tag === 'since';
	} );

	sinceTags.forEach( ( tag, index ) => {
		const previousTag = sinceTags[ index - 1 ] || null;

		if ( ! tag.description || ! tag.description.length ) {
			context.report( {
				data: { name: jsdocNode.name },
				message: 'The @since tag cannot be empty.',
				node: jsdocNode,
			} );

			return;
		}

		const [ versionString ] = tag.description.split( ' ', 1 );

		if ( versionString !== 'n.e.x.t' && ! semverRegex().test( versionString ) ) {
			context.report( {
				data: { name: jsdocNode.name },
				message: 'The @since tag requires a valid semVer value or the "n.e.x.t" label.',
				node: jsdocNode,
			} );

			return;
		}

		const description = tag.description.slice( versionString.length );

		if ( ! description || ! description.length ) {
			// The first since tag doesn't require a description.
			if ( index === 0 ) {
				return;
			}

			context.report( {
				data: { name: jsdocNode.name },
				message: 'All @since tags after the first require a description.',
				node: jsdocNode,
			} );

			return;
		}

		if (
			// Ignore if the first character is a backtick; this is often used
			// when marking return values like `true` or `null`.
			// Also ignore parens and quotes.
			! description.trim().match( /^[A-Z`("].*/gm )
		) {
			context.report( {
				data: { name: jsdocNode.name },
				message: `All @since tags should have a description starting with a capital letter.`,
				node: jsdocNode,
			} );

			return;
		}

		if ( ! description.match( /\.$/gm ) ) {
			context.report( {
				data: { name: jsdocNode.name },
				message: `All @since tags should have a description that ends with a period/full-stop.`,
				node: jsdocNode,
			} );

			return;
		}

		if ( previousTag ) {
			const [ previousVersionString ] = previousTag.description.split( ' ', 1 );

			if ( semverRegex().test( versionString ) && semverRegex().test( previousVersionString ) && semverCompare( versionString, previousVersionString ) === 0 ) {
				context.report( {
					data: { name: jsdocNode.name },
					message: `Each version should have only one @since tag.`,
					node: jsdocNode,
				} );

				return;
			}

			if ( semverRegex().test( versionString ) && semverRegex().test( previousVersionString ) && semverCompare( versionString, previousVersionString ) !== -1 ) {
				context.report( {
					data: { name: jsdocNode.name },
					message: `@since tags should appear in order of version number.`,
					node: jsdocNode,
				} );
			}
		}
	} );
}, {
	iterateAllJsdocs: true,
	meta: {
		docs: {
			description: 'Requires that all functions have a `@since` tag.',
		},
		fixable: 'code',
		type: 'suggestion',
	},
} );
<commit_msg>Fix since version ordering rule.<commit_after>/**
 * ESLint rules: Require the @since tag in JSDoc.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
const { default: iterateJsdoc } = require( 'eslint-plugin-jsdoc/dist/iterateJsdoc' );
const semverCompare = require( 'semver-compare' );
const semverRegex = require( 'semver-regex' );

module.exports = iterateJsdoc( ( {
	context,
	jsdoc,
	jsdocNode,
	utils,
} ) => {
	if ( ! jsdoc.tags || ! jsdoc.tags.length ) {
		return;
	}

	// If the `@ignore` tag is in this JSDoc block, ignore it and don't require a `@since` tag.
	if ( utils.hasTag( 'ignore' ) ) {
		return;
	}

	if ( ! utils.hasTag( 'since' ) ) {
		context.report( {
			data: { name: jsdocNode.name },
			message: `Missing @since tag in JSDoc.`,
			node: jsdocNode,
		} );

		return;
	}

	// Get all @since tags and make sure the format is correct.
	const sinceTags = utils.filterTags( ( { tag } ) => {
		return tag === 'since';
	} );

	sinceTags.forEach( ( tag, index ) => {
		const previousTag = sinceTags[ index - 1 ] || null;

		if ( ! tag.description || ! tag.description.length ) {
			context.report( {
				data: { name: jsdocNode.name },
				message: 'The @since tag cannot be empty.',
				node: jsdocNode,
			} );

			return;
		}

		const [ versionString ] = tag.description.split( ' ', 1 );

		if ( versionString !== 'n.e.x.t' && ! semverRegex().test( versionString ) ) {
			context.report( {
				data: { name: jsdocNode.name },
				message: 'The @since tag requires a valid semVer value or the "n.e.x.t" label.',
				node: jsdocNode,
			} );

			return;
		}

		const description = tag.description.slice( versionString.length );

		if ( ! description || ! description.length ) {
			// The first since tag doesn't require a description.
			if ( index === 0 ) {
				return;
			}

			context.report( {
				data: { name: jsdocNode.name },
				message: 'All @since tags after the first require a description.',
				node: jsdocNode,
			} );

			return;
		}

		if (
			// Ignore if the first character is a backtick; this is often used
			// when marking return values like `true` or `null`.
			// Also ignore parens and quotes.
			! description.trim().match( /^[A-Z`("].*/gm )
		) {
			context.report( {
				data: { name: jsdocNode.name },
				message: `All @since tags should have a description starting with a capital letter.`,
				node: jsdocNode,
			} );

			return;
		}

		if ( ! description.match( /\.$/gm ) ) {
			context.report( {
				data: { name: jsdocNode.name },
				message: `All @since tags should have a description that ends with a period/full-stop.`,
				node: jsdocNode,
			} );

			return;
		}

		if ( previousTag ) {
			const [ previousVersionString ] = previousTag.description.split( ' ', 1 );

			if ( semverRegex().test( versionString ) && semverRegex().test( previousVersionString ) && semverCompare( versionString, previousVersionString ) === 0 ) {
				context.report( {
					data: { name: jsdocNode.name },
					message: `Each version should have only one @since tag.`,
					node: jsdocNode,
				} );

				return;
			}

			if ( semverRegex().test( versionString ) && semverRegex().test( previousVersionString ) && semverCompare( versionString, previousVersionString ) !== 1 ) {
				context.report( {
					data: { name: jsdocNode.name },
					message: `@since tags should appear in order of version number.`,
					node: jsdocNode,
				} );
			}
		}
	} );
}, {
	iterateAllJsdocs: true,
	meta: {
		docs: {
			description: 'Requires that all functions have a `@since` tag.',
		},
		fixable: 'code',
		type: 'suggestion',
	},
} );
<|endoftext|>


<commit_before>/**
 * A simple table editor. It shall convert a cell into an input on click, touch
 * or focus. It shall convert back the input into cell on focus lost or key
 * navigation. Input type can be set on column.
 */
(function($) {
	"use strict";
	function getChildrenIndex(child) {
		var i = 0;
		var current = child;
		while(current.previousSibling) {
			i++;
			current = current.previousSibling;
		}
		return i;
	}
	function makeNewEditableCell(theTable, tableEditableOptions, theColModel) {
		var colEditableOptions = theColModel['editableOptions'] ? theColModel['editableOptions']
				: {};
		var options = $.extend({}, tableEditableOptions, colEditableOptions);
		var userCallback = options['callback'];
		options['callback'] = function(value, settings) {
			if (userCallback) {
				userCallback.apply(value, settings);
			}
			var onChange = theTable.data('jqEditableTable')['onChange'];
			if (onChange) {
				onChange.apply(theTable);
			}
			return value;
		};
		var newCell = $('<td>').editable(function(value, settings) {
			return value;
		}, options);
		// Handle keypress to navigate into the table
		newCell.keypress(function(e) {
			var code = e.keyCode ? e.keyCode : e.which;
			var cellToEditAfter = undefined;
			switch (code) {
			case 9:
				if (e.shiftKey) { // backward tabulation
					// input -> form -> td -> previous td
					cellToEditAfter = e.target.parentNode.parentNode.previousSibling;
					if (cellToEditAfter === null) {
						var children = e.target.parentNode.parentNode.parentNode.previousSibling.children;
						cellToEditAfter = children[children.length-1];
					}
				} else { //  forward tabulation
					// input -> form -> td -> next td
					cellToEditAfter = e.target.parentNode.parentNode.nextSibling;
					if (cellToEditAfter === null) {
						// input -> form -> td -> tr -> next tr -> first td
						cellToEditAfter = e.target.parentNode.parentNode.parentNode.nextSibling.children[0];
					}
				}
				break;
			case 38: // handle up
				var thisIndex = getChildrenIndex(e.target.parentNode.parentNode);
				// input -> form -> td -> tr -> previous tr -> td with same index
				cellToEditAfter = e.target.parentNode.parentNode.parentNode.previousSibling.children[thisIndex];
				break;
			case 40: // handle down
				var thisIndex = getChildrenIndex(e.target.parentNode.parentNode);
				// input -> form -> td -> tr -> next tr -> td with same index
				cellToEditAfter = e.target.parentNode.parentNode.parentNode.nextSibling.children[thisIndex];
				break;
			}
			if (cellToEditAfter) {
				$(e.target).blur();
				$(cellToEditAfter).click();
				e.preventDefault();
			}
		});
		return newCell;
	}
	var methods = {
		init : function(options) {
			var colModels = options['colModel'];
			if (colModels) {
				var colIndex;
				for (colIndex in colModels) {
					var aColModel = colModels[colIndex];
					this.jqEditableTable('addColumn', aColModel);
				}
			}
			this.data('jqEditableTable', options);
			return this;
		},
		getTHead : function() {
			// Get or create thead
			var theads = this.children('thead');
			if (theads.length === 0) {
				var newTHead = $('<thead>');
				theads = newTHead;
				this.append(newTHead);
			}
			return theads;
		},
		getTHeadRow : function() {
			var theads = this.jqEditableTable('getTHead');
			// Get or create thead/tr
			var thRow = theads.children('tr');
			if (thRow.length === 0) {
				var newThRow = $('<tr>');
				thRow = newThRow;
				theads.append(newThRow);
			}
			return thRow;
		},
		getTBody : function() {
			// Get or create tbody
			var tbodies = this.children('tbody');
			if (tbodies.length === 0) {
				var newTBody = $('<tbody>');
				tbodies = newTBody;
				this.append(newTBody);
			}
			return tbodies;
		},
		addColumn : function addColumn(aColModel) {
			var thRow = this.jqEditableTable('getTHeadRow');
			// Create thead/tr/th
			var colLabel = aColModel['label'] === undefined ? aColModel['name']
					: aColModel['label'];
			thRow.append($('<th>').append(colLabel));

			// Add td to all existing rows
			// but first assert tbody exist.
			var tbodies = this.jqEditableTable('getTBody');
			var allTRs = tbodies.children('tr');
			if (allTRs.length !== 0) {
				allTRs.append(makeNewEditableCell(this,
						this.data('jqEditableTable')['editableOptions'], aColModel));
			}
			return this;
		},
		getColumnSize : function() {
			return this.jqEditableTable('getTHeadRow').children('th').length;
		},
		addRow : function(someData) {
			var tbodies = this.jqEditableTable('getTBody');
			var editableOptions = this.data('jqEditableTable')['editableOptions'];
			if (Object.prototype.toString.call(someData) === '[object Array]') {
				var colIndex;
				var theColModel;
				var colModels = this.data('jqEditableTable')['colModel'];
				var newRow = $('<tr>');
				for (colIndex in someData) {
					theColModel = colModels[colIndex];
					newRow.append(makeNewEditableCell(this, editableOptions,
							theColModel).html(someData[colIndex]));
				}
				var columnSize = this.jqEditableTable('getColumnSize');
				if (colIndex === undefined) {
					colIndex = 0;
				} else {
					colIndex++;
				}
				for (; colIndex < columnSize; colIndex++) {
					theColModel = colModels[colIndex];
					newRow.append(makeNewEditableCell(this, editableOptions,
							theColModel));
				}
				tbodies.append(newRow);
			}
		},
		getColumnsName : function() {
			return this.data('jqEditableTable')['colModel'].map(function(aColModel) {
				return aColModel['name'];
			});
		},
		getRowData : function() {
			var columns = this.jqEditableTable('getColumnsName');
			var tbodies = this.jqEditableTable('getTBody');
			var allTRs = tbodies.children('tr');
			var data = [];
			allTRs.each(function(index, value) {
				var row = {};
				$(value).children('td').each(function(childIndex, child) {
					row[columns[childIndex]] = $(child).text();
				});
				data.push(row);
			});
			return data;
		},
		toCSV : function() {
			var columns = this.jqEditableTable('getColumnsName');
			var data = this.jqEditableTable('getRowData');
			var csv = "";
			var i;
			for (i = 0; i < columns.length; i++) {
				csv += '"' + columns[i] + '"';
				if (i < columns.length - 1) {
					csv += ', ';
				}
			}
			csv += "\n";
			var row;
			var j;
			for (i = 0; i < data.length; i++) {
				row = data[i];
				for (j = 0; j < columns.length; j++) {
					csv += '"' + row[columns[j]] + '"';
					if (j < columns.length - 1) {
						csv += ', ';
					}
				}
				csv += "\n";
			}
			return csv;
		}
	};

	$.fn.jqEditableTable = function(method) {
		if (methods[method]) {
			return methods[method].apply(this, Array.prototype.slice.call(
					arguments, 1));
		} else if (typeof method === 'object' || !method) {
			return methods.init.apply(this, arguments);
		} else {
			$.error('Method ' + method + ' does not exist on jQuery.jqEditableTable');
		}
	};
})(jQuery);<commit_msg>Calling twice addColumn on same colModel (ie same name value) will just update the model, not the table.<commit_after>/**
 * A simple table editor. It shall convert a cell into an input on click, touch
 * or focus. It shall convert back the input into cell on focus lost or key
 * navigation. Input type can be set on column.
 */
(function($) {
	"use strict";
	function getChildrenIndex(child) {
		var i = 0;
		var current = child;
		while(current.previousSibling) {
			i++;
			current = current.previousSibling;
		}
		return i;
	}
	function makeNewEditableCell(theTable, tableEditableOptions, theColModel) {
		var colEditableOptions = theColModel['editableOptions'] ? theColModel['editableOptions']
				: {};
		var options = $.extend({}, tableEditableOptions, colEditableOptions);
		var userCallback = options['callback'];
		options['callback'] = function(value, settings) {
			if (userCallback) {
				userCallback.apply(value, settings);
			}
			var onChange = theTable.data('jqEditableTable')['onChange'];
			if (onChange) {
				onChange.apply(theTable);
			}
			return value;
		};
		var newCell = $('<td>').editable(function(value, settings) {
			return value;
		}, options);
		// Handle keypress to navigate into the table
		newCell.keypress(function(e) {
			var code = e.keyCode ? e.keyCode : e.which;
			var cellToEditAfter = undefined;
			switch (code) {
			case 9:
				if (e.shiftKey) { // backward tabulation
					// input -> form -> td -> previous td
					cellToEditAfter = e.target.parentNode.parentNode.previousSibling;
					if (cellToEditAfter === null) {
						var children = e.target.parentNode.parentNode.parentNode.previousSibling.children;
						cellToEditAfter = children[children.length-1];
					}
				} else { //  forward tabulation
					// input -> form -> td -> next td
					cellToEditAfter = e.target.parentNode.parentNode.nextSibling;
					if (cellToEditAfter === null) {
						// input -> form -> td -> tr -> next tr -> first td
						cellToEditAfter = e.target.parentNode.parentNode.parentNode.nextSibling.children[0];
					}
				}
				break;
			case 38: // handle up
				var thisIndex = getChildrenIndex(e.target.parentNode.parentNode);
				// input -> form -> td -> tr -> previous tr -> td with same index
				cellToEditAfter = e.target.parentNode.parentNode.parentNode.previousSibling.children[thisIndex];
				break;
			case 40: // handle down
				var thisIndex = getChildrenIndex(e.target.parentNode.parentNode);
				// input -> form -> td -> tr -> next tr -> td with same index
				cellToEditAfter = e.target.parentNode.parentNode.parentNode.nextSibling.children[thisIndex];
				break;
			}
			if (cellToEditAfter) {
				$(e.target).blur();
				$(cellToEditAfter).click();
				e.preventDefault();
			}
		});
		return newCell;
	}
	var methods = {
		init : function(options) {
			var colModels = options['colModel'];
			if (colModels) {
				var colIndex;
				for (colIndex in colModels) {
					var aColModel = colModels[colIndex];
					this.jqEditableTable('addColumn', aColModel);
				}
			}
			this.data('jqEditableTable', options);
			return this;
		},
		getTHead : function() {
			// Get or create thead
			var theads = this.children('thead');
			if (theads.length === 0) {
				var newTHead = $('<thead>');
				theads = newTHead;
				this.append(newTHead);
			}
			return theads;
		},
		getTHeadRow : function() {
			var theads = this.jqEditableTable('getTHead');
			// Get or create thead/tr
			var thRow = theads.children('tr');
			if (thRow.length === 0) {
				var newThRow = $('<tr>');
				thRow = newThRow;
				theads.append(newThRow);
			}
			return thRow;
		},
		getTBody : function() {
			// Get or create tbody
			var tbodies = this.children('tbody');
			if (tbodies.length === 0) {
				var newTBody = $('<tbody>');
				tbodies = newTBody;
				this.append(newTBody);
			}
			return tbodies;
		},
		addColumn : function addColumn(aColModel) {
			// Append the new column model into colModel list
			var data = this.data('jqEditableTable');
			if (data) {
				var colModels = data['colModel'];
				var colIndex;
				for(colIndex in colModels) {
					if (colModels[colIndex].name === aColModel.name) {
						// There is already such a column thus do not add it just update colModel
						colModels[colIndex] = $.extend({}, aColModel, colModels[colIndex]);
						this.data('jqEditableTable')['colModel'] = colModels;
						return this;
					}
				}
				colModels.push(aColModel);
			}

			var thRow = this.jqEditableTable('getTHeadRow');
			// Create thead/tr/th
			var colLabel = aColModel['label'] === undefined ? aColModel['name']
					: aColModel['label'];
			thRow.append($('<th>').append(colLabel));

			// Add td to all existing rows
			// but first assert tbody exist.
			var tbodies = this.jqEditableTable('getTBody');
			var allTRs = tbodies.children('tr');
			if (allTRs.length !== 0) {
				allTRs.append(makeNewEditableCell(this,
						this.data('jqEditableTable')['editableOptions'], aColModel));
			}
			return this;
		},
		getColumnSize : function() {
			return this.jqEditableTable('getTHeadRow').children('th').length;
		},
		addRow : function(someData) {
			var tbodies = this.jqEditableTable('getTBody');
			var editableOptions = this.data('jqEditableTable')['editableOptions'];
			if (Object.prototype.toString.call(someData) === '[object Array]') {
				var colIndex;
				var theColModel;
				var colModels = this.data('jqEditableTable')['colModel'];
				var newRow = $('<tr>');
				for (colIndex in someData) {
					theColModel = colModels[colIndex];
					newRow.append(makeNewEditableCell(this, editableOptions,
							theColModel).html(someData[colIndex]));
				}
				var columnSize = this.jqEditableTable('getColumnSize');
				if (colIndex === undefined) {
					colIndex = 0;
				} else {
					colIndex++;
				}
				for (; colIndex < columnSize; colIndex++) {
					theColModel = colModels[colIndex];
					newRow.append(makeNewEditableCell(this, editableOptions,
							theColModel));
				}
				tbodies.append(newRow);
			}
		},
		getColumnsName : function() {
			return this.data('jqEditableTable')['colModel'].map(function(aColModel) {
				return aColModel['name'];
			});
		},
		getRowData : function() {
			var columns = this.jqEditableTable('getColumnsName');
			var tbodies = this.jqEditableTable('getTBody');
			var allTRs = tbodies.children('tr');
			var data = [];
			allTRs.each(function(index, value) {
				var row = {};
				$(value).children('td').each(function(childIndex, child) {
					row[columns[childIndex]] = $(child).text();
				});
				data.push(row);
			});
			return data;
		},
		toCSV : function() {
			var columns = this.jqEditableTable('getColumnsName');
			var data = this.jqEditableTable('getRowData');
			var csv = "";
			var i;
			for (i = 0; i < columns.length; i++) {
				csv += '"' + columns[i] + '"';
				if (i < columns.length - 1) {
					csv += ', ';
				}
			}
			csv += "\n";
			var row;
			var j;
			for (i = 0; i < data.length; i++) {
				row = data[i];
				for (j = 0; j < columns.length; j++) {
					csv += '"' + row[columns[j]] + '"';
					if (j < columns.length - 1) {
						csv += ', ';
					}
				}
				csv += "\n";
			}
			return csv;
		}
	};

	$.fn.jqEditableTable = function(method) {
		if (methods[method]) {
			return methods[method].apply(this, Array.prototype.slice.call(
					arguments, 1));
		} else if (typeof method === 'object' || !method) {
			return methods.init.apply(this, arguments);
		} else {
			$.error('Method ' + method + ' does not exist on jQuery.jqEditableTable');
		}
	};
})(jQuery);<|endoftext|>


<commit_before>import async from 'async';

export default class Transloadit {
  constructor(opts) {
    // Dictates in what order different plugin types are ran:
    this.types = [ 'presetter', 'selecter', 'uploader' ];

    // Container for different types of plugins
    this.plugins = {};
  }

  use(Plugin, opts) {
    // Instantiate
    var plugin = new Plugin(this, opts);
    this.plugins[plugin.type] = this.plugins[plugin.type] || [];
    this.plugins[plugin.type].push(plugin);

    return this;
  }

  setProgress(plugin, percentage) {
    // Any plugin can call this via `this.core.setProgress(this, precentage)`
    console.log(plugin.type + ' plugin ' + plugin.name + ' set the progress to ' + percentage);

    return this;
  }

  runType(type, files, cb) {
    console.dir({
      method: 'Transloadit.runType',
      type  : type,
      files : files,
      cb    : cb
    });

    const methods = [];
    for (let p in this.plugins[type]) {
      const plugin = this.plugins[type][p];
      methods.push(plugin.run.bind(plugin, files));
    }

    async.parallel(methods, cb);
  }

  run() {
    console.dir({
      method: 'Transloadit.run'
    });

    var typeMethods = [];
    typeMethods.push(async.constant([]));

    for (let t in this.types) {
      const type = this.types[t];
      typeMethods.push(this.runType.bind(this, type));
    }

    async.waterfall(typeMethods, function (err, finalFiles) {
      console.dir({
        err       :err,
        finalFiles:finalFiles
      })
    });
  }
}
<commit_msg>Resolved small conflict<commit_after>import async from 'async';

export default class Transloadit {
  constructor(opts) {
    // Dictates in what order different plugin types are ran:
    this.types = [ 'presetter', 'selecter', 'uploader' ];

    // Container for different types of plugins
    this.plugins = {};
  }

  use(Plugin, opts) {
    // Instantiate
    var plugin = new Plugin(this, opts);
    this.plugins[plugin.type] = this.plugins[plugin.type] || [];
    this.plugins[plugin.type].push(plugin);

    return this;
  }

  setProgress(plugin, percentage) {
    // Any plugin can call this via `this.core.setProgress(this, precentage)`
    console.log(plugin.type + ' plugin ' + plugin.name + ' set the progress to ' + percentage);

    return this;
  }

  runType(type, files, cb) {
    console.dir({
      method: 'Transloadit.runType',
      type  : type,
      files : files,
      cb    : cb
    });

    const methods = [];
    for (let p in this.plugins[type]) {
      const plugin = this.plugins[type][p];
      methods.push(plugin.run.bind(plugin, files));
    }

    async.parallel(methods, cb);
  }

  run() {
    console.dir({
      method: 'Transloadit.run'
    });

    var typeMethods = [];
    typeMethods.push(async.constant([]));

    for (let t in this.types) {
      const type = this.types[t];
      typeMethods.push(this.runType.bind(this, type));
    }

    async.waterfall(typeMethods, function (err, finalFiles) {
      console.dir({
        err       : err ,
        finalFiles: finalFiles
      });
    });
  }
}
<|endoftext|>


<commit_before>const webpack = require("webpack");
const config = require("./webpack.config.base");

config.mode = "development";

config.module.rules.push(
    {
        enforce: "pre",
        test: /\.jsx?$/,
        use: ["eslint-loader"],
        exclude: /node_modules/
    },
    {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
    },
    {
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
        include: /node_modules/
    },
    {
        test: /\.less$/,
        use: [
            "style-loader",
            {
                loader: "css-loader",
                options: {
                    modules: true,
                    sourceMap: true,
                    localIdentName: "[name]-[local]"
                }
            },
            "less-loader"
        ],
        exclude: /node_modules/
    }
);

// Hot module replacement, see https://github.com/gaearon/react-hot-loader#getting-started
for (const key of Object.keys(config.entry))
{
    config.entry[key].unshift("webpack-hot-middleware/client?quiet=true");
}
config.plugins.push(
    new webpack.HotModuleReplacementPlugin()
);

module.exports = config;
<commit_msg>format<commit_after>const webpack = require("webpack");
const config = require("./webpack.config.base");

config.mode = "development";

config.module.rules.push(
    {
        enforce: "pre",
        test: /\.jsx?$/,
        use: ["eslint-loader"],
        exclude: /node_modules/
    },
    {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
    },
    {
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
        include: /node_modules/
    },
    {
        test: /\.less$/,
        use: [
            "style-loader",
            {
                loader: "css-loader",
                options: {
                    modules: true,
                    sourceMap: true,
                    localIdentName: "[name]-[local]"
                }
            },
            "less-loader"
        ],
        exclude: /node_modules/
    }
);

// Hot module replacement, see https://github.com/gaearon/react-hot-loader#getting-started
for (const key of Object.keys(config.entry))
{
    config.entry[key].unshift("webpack-hot-middleware/client?quiet=true");
}
config.plugins.push(new webpack.HotModuleReplacementPlugin());

module.exports = config;
<|endoftext|>


<commit_before>window.TopbarView = Backbone.View.extend({

    tagName: 'header',
    className: 'topbar',

    events: {
        "click a.menu": "showDropdown",
        "submit form": "onSearchSubmit"
    },

    initialize: function () {
        window.app.user.bind('login', this.onLogin, this);
    },

    render: function () {
        this.$el.html(templates.topbarView);
        $('#container').append(this.el);

        this.$('ul li.menu, ul li.user').each(function () {
            $(this).css('display', 'block').hide();
        });
        return this;
    },

    hideNavigation: function () {
        this.$('ul').hide();
    },

    hideDropdown: function () {
        this.$('li.menu').removeClass('open');
    },

    showDropdown: function () {
        this.$('li.menu').toggleClass('open');
        return false; // Return false stops the click event from propagating (for example to the body event)
    },

    onSearchSubmit: function (evt) {
        if (!window.nomApi)
            window.nomApi = new Nominatim();

        var s = this.$('form input[type=text]').val(),
            that = this;
        nomApi.search(s, function (success, data) {
            var spot = null;
            for (var i in data) {
                if (data[i]["class"] == "place") {
                    spot = data[i];
                    break;
                }
            }

            if (_.isNull(spot)) {
                new MessageView({title: $._("Error"), message: $._("Couldn't find the spot")}).render();
                return;
            }

            window.map.setCenter({lon: spot.lon, lat: spot.lat}, spot.boundingbox);
        });

        evt.preventDefault();
        return false;
    },

    onLogin: function (login) {
        var user = window.app.user;

        if (user.isLoggedIn()) {
            this.$('li.user a').html(user.get('firstname') + ' ' + user.get('lastname'));
            this.$('li.user, li.menu').show();

            if (user.get('admin'))
                this.$('li.menu ul li.admin').show();
        } else {
            this.$('li.user, li.menu').hide();
            this.$('li.menu ul li.admin').hide();
        }
    }

});
<commit_msg>Fix nominatim api<commit_after>window.TopbarView = Backbone.View.extend({

    tagName: 'header',
    className: 'topbar',

    events: {
        "click a.menu": "showDropdown",
        "submit form": "onSearchSubmit"
    },

    initialize: function () {
        window.app.user.bind('login', this.onLogin, this);
    },

    render: function () {
        this.$el.html(templates.topbarView);
        $('#container').append(this.el);

        this.$('ul li.menu, ul li.user').each(function () {
            $(this).css('display', 'block').hide();
        });
        return this;
    },

    hideNavigation: function () {
        this.$('ul').hide();
    },

    hideDropdown: function () {
        this.$('li.menu').removeClass('open');
    },

    showDropdown: function () {
        this.$('li.menu').toggleClass('open');
        return false; // Return false stops the click event from propagating (for example to the body event)
    },

    onSearchSubmit: function (evt) {
        if (!window.nomApi)
            window.nomApi = new Nominatim();

        var s = this.$('form input[type=search]').val(),
            that = this;
        nomApi.search(s, function (success, data) {
            var spot = null;
            for (var i in data) {
                if (data[i]["class"] == "boundary")
                    continue;
                spot = data[i];
                break;
            }

            if (_.isNull(spot)) {
                new MessageView({title: $._("Error"), message: $._("Couldn't find the spot")}).render();
                return;
            }

            window.map.setCenter({lon: spot.lon, lat: spot.lat}, spot.boundingbox);
        });

        evt.preventDefault();
        return false;
    },

    onLogin: function (login) {
        var user = window.app.user;

        if (user.isLoggedIn()) {
            this.$('li.user a').html(user.get('firstname') + ' ' + user.get('lastname'));
            this.$('li.user, li.menu').show();

            if (user.get('admin'))
                this.$('li.menu ul li.admin').show();
        } else {
            this.$('li.user, li.menu').hide();
            this.$('li.menu ul li.admin').hide();
        }
    }

});
<|endoftext|>


<commit_before>'use strict';

var translate = require('./i18n').translate;

/**
 * A factory function to create an ShowMoreNode, which depends on a Node
 * @param {function} Node
 */
function showMoreNodeFactory(Node) {
  /**
   * @constructor ShowMoreNode
   * @extends Node
   * @param {TreeEditor} editor
   * @param {Node} parent
   * Create a new ShowMoreNode. This is a special node which is created
   * for arrays or objects having more than 100 items
   */
  function ShowMoreNode (editor, parent) {
    /** @type {TreeEditor} */
    this.editor = editor;
    this.parent = parent;
    this.dom = {};
  }

  ShowMoreNode.prototype = new Node();

  /**
   * Return a table row with an append button.
   * @return {Element} dom   TR element
   */
  ShowMoreNode.prototype.getDom = function () {
    if (this.dom.tr) {
      return this.dom.tr;
    }

    this._updateEditability();

    // display "show more"
    if (!this.dom.tr) {
      var me = this;
      var parent = this.parent;
      var showMoreButton = document.createElement('a');
      showMoreButton.appendChild(document.createTextNode('show\u00A0more'));
      showMoreButton.href = '#';
      showMoreButton.onclick = function (event) {
        // TODO: use callback instead of accessing a method of the parent
        parent.maxVisibleChilds += Node.prototype.MAX_VISIBLE_CHILDS;
        me.updateDom();
        parent.showChilds();

        event.preventDefault();
        return false;
      };

      var showAllButton = document.createElement('a');
      showAllButton.appendChild(document.createTextNode('show\u00A0all'));
      showAllButton.href = '#';
      showAllButton.onclick = function (event) {
        // TODO: use callback instead of accessing a method of the parent
        parent.maxVisibleChilds = Infinity;
        me.updateDom();
        parent.showChilds();

        event.preventDefault();
        return false;
      };

      var moreContents = document.createElement('div');
      var moreText = document.createTextNode(this._getShowMoreText());
      moreContents.className = 'jsoneditor-show-more';
      moreContents.appendChild(moreText);
      moreContents.appendChild(showMoreButton);
      moreContents.appendChild(document.createTextNode('. '));
      moreContents.appendChild(showAllButton);
      moreContents.appendChild(document.createTextNode('. '));

      var tdContents = document.createElement('td');
      tdContents.appendChild(moreContents);

      var moreTr = document.createElement('tr');
      moreTr.appendChild(document.createElement('td'));
      moreTr.appendChild(document.createElement('td'));
      moreTr.appendChild(tdContents);
      this.dom.tr = moreTr;
      this.dom.moreContents = moreContents;
      this.dom.moreText = moreText;
    }

    this.updateDom();

    return this.dom.tr;
  };

  /**
   * Update the HTML dom of the Node
   */
  ShowMoreNode.prototype.updateDom = function(options) {
    if (this.isVisible()) {
      // attach to the right child node (the first non-visible child)
      this.dom.tr.node = this.parent.childs[this.parent.maxVisibleChilds];

      if (!this.dom.tr.parentNode) {
        var nextTr = this.parent._getNextTr();
        if (nextTr) {
          nextTr.parentNode.insertBefore(this.dom.tr, nextTr);
        }
      }

      // update the counts in the text
      this.dom.moreText.nodeValue = this._getShowMoreText();

      // update left margin
      this.dom.moreContents.style.marginLeft = (this.getLevel() + 1) * 24 + 'px';
    }
    else {
      if (this.dom.tr && this.dom.tr.parentNode) {
        this.dom.tr.parentNode.removeChild(this.dom.tr);
      }
    }
  };

  ShowMoreNode.prototype._getShowMoreText = function() {
    // TODO: implement in translate
    var childs = this.type === 'array' ? 'items' : 'properties';
    return 'displaying ' + this.parent.maxVisibleChilds +
        ' of ' + this.parent.childs.length + ' ' + childs + '. ';
  };

  /**
   * Check whether the ShowMoreNode is currently visible.
   * the ShowMoreNode is visible when it's parent has more childs than
   * the current maxVisibleChilds
   * @return {boolean} isVisible
   */
  ShowMoreNode.prototype.isVisible = function () {
    return this.parent.expanded && this.parent.childs.length > this.parent.maxVisibleChilds;
  };

  /**
   * Handle an event. The event is caught centrally by the editor
   * @param {Event} event
   */
  ShowMoreNode.prototype.onEvent = function (event) {
    var type = event.type;
    // var target = event.target || event.srcElement;
    // var dom = this.dom;

    // // highlight the append nodes parent
    // var menu = dom.menu;
    // if (target == menu) {
    //   if (type == 'mouseover') {
    //     this.editor.highlighter.highlight(this.parent);
    //   }
    //   else if (type == 'mouseout') {
    //     this.editor.highlighter.unhighlight();
    //   }
    // }

    // // context menu events
    // if (type == 'click' && target == dom.menu) {
    //   var highlighter = this.editor.highlighter;
    //   highlighter.highlight(this.parent);
    //   highlighter.lock();
    //   util.addClassName(dom.menu, 'jsoneditor-selected');
    //   this.showContextMenu(dom.menu, function () {
    //     util.removeClassName(dom.menu, 'jsoneditor-selected');
    //     highlighter.unlock();
    //     highlighter.unhighlight();
    //   });
    // }

    if (type === 'keydown') {
      this.onKeyDown(event);
    }
  };

  return ShowMoreNode;
}

module.exports = showMoreNodeFactory;
<commit_msg>Cleanup commented code<commit_after>'use strict';

var translate = require('./i18n').translate;

/**
 * A factory function to create an ShowMoreNode, which depends on a Node
 * @param {function} Node
 */
function showMoreNodeFactory(Node) {
  /**
   * @constructor ShowMoreNode
   * @extends Node
   * @param {TreeEditor} editor
   * @param {Node} parent
   * Create a new ShowMoreNode. This is a special node which is created
   * for arrays or objects having more than 100 items
   */
  function ShowMoreNode (editor, parent) {
    /** @type {TreeEditor} */
    this.editor = editor;
    this.parent = parent;
    this.dom = {};
  }

  ShowMoreNode.prototype = new Node();

  /**
   * Return a table row with an append button.
   * @return {Element} dom   TR element
   */
  ShowMoreNode.prototype.getDom = function () {
    if (this.dom.tr) {
      return this.dom.tr;
    }

    this._updateEditability();

    // display "show more"
    if (!this.dom.tr) {
      var me = this;
      var parent = this.parent;
      var showMoreButton = document.createElement('a');
      showMoreButton.appendChild(document.createTextNode('show\u00A0more'));
      showMoreButton.href = '#';
      showMoreButton.onclick = function (event) {
        // TODO: use callback instead of accessing a method of the parent
        parent.maxVisibleChilds += Node.prototype.MAX_VISIBLE_CHILDS;
        me.updateDom();
        parent.showChilds();

        event.preventDefault();
        return false;
      };

      var showAllButton = document.createElement('a');
      showAllButton.appendChild(document.createTextNode('show\u00A0all'));
      showAllButton.href = '#';
      showAllButton.onclick = function (event) {
        // TODO: use callback instead of accessing a method of the parent
        parent.maxVisibleChilds = Infinity;
        me.updateDom();
        parent.showChilds();

        event.preventDefault();
        return false;
      };

      var moreContents = document.createElement('div');
      var moreText = document.createTextNode(this._getShowMoreText());
      moreContents.className = 'jsoneditor-show-more';
      moreContents.appendChild(moreText);
      moreContents.appendChild(showMoreButton);
      moreContents.appendChild(document.createTextNode('. '));
      moreContents.appendChild(showAllButton);
      moreContents.appendChild(document.createTextNode('. '));

      var tdContents = document.createElement('td');
      tdContents.appendChild(moreContents);

      var moreTr = document.createElement('tr');
      moreTr.appendChild(document.createElement('td'));
      moreTr.appendChild(document.createElement('td'));
      moreTr.appendChild(tdContents);
      this.dom.tr = moreTr;
      this.dom.moreContents = moreContents;
      this.dom.moreText = moreText;
    }

    this.updateDom();

    return this.dom.tr;
  };

  /**
   * Update the HTML dom of the Node
   */
  ShowMoreNode.prototype.updateDom = function(options) {
    if (this.isVisible()) {
      // attach to the right child node (the first non-visible child)
      this.dom.tr.node = this.parent.childs[this.parent.maxVisibleChilds];

      if (!this.dom.tr.parentNode) {
        var nextTr = this.parent._getNextTr();
        if (nextTr) {
          nextTr.parentNode.insertBefore(this.dom.tr, nextTr);
        }
      }

      // update the counts in the text
      this.dom.moreText.nodeValue = this._getShowMoreText();

      // update left margin
      this.dom.moreContents.style.marginLeft = (this.getLevel() + 1) * 24 + 'px';
    }
    else {
      if (this.dom.tr && this.dom.tr.parentNode) {
        this.dom.tr.parentNode.removeChild(this.dom.tr);
      }
    }
  };

  ShowMoreNode.prototype._getShowMoreText = function() {
    // TODO: implement in translate
    var childs = this.type === 'array' ? 'items' : 'properties';
    return 'displaying ' + this.parent.maxVisibleChilds +
        ' of ' + this.parent.childs.length + ' ' + childs + '. ';
  };

  /**
   * Check whether the ShowMoreNode is currently visible.
   * the ShowMoreNode is visible when it's parent has more childs than
   * the current maxVisibleChilds
   * @return {boolean} isVisible
   */
  ShowMoreNode.prototype.isVisible = function () {
    return this.parent.expanded && this.parent.childs.length > this.parent.maxVisibleChilds;
  };

  /**
   * Handle an event. The event is caught centrally by the editor
   * @param {Event} event
   */
  ShowMoreNode.prototype.onEvent = function (event) {
    var type = event.type;
    if (type === 'keydown') {
      this.onKeyDown(event);
    }
  };

  return ShowMoreNode;
}

module.exports = showMoreNodeFactory;
<|endoftext|>


<commit_before>YUI.add("view-timeline", function(Y) {
    "use strict";

    var moment     = require("moment"),
        text       = require("twitter-text"),

        falco      = Y.namespace("Falco"),
        extensions = Y.namespace("Falco.Extensions"),
        templates  = Y.namespace("Falco.Templates"),

        _options, _newlineRegex, _nl2br, Timeline;

    _options = {
        "data-external" : ""
    };

    _newlineRegex = /(?:\r\n|\n|\r)/g;
    _nl2br = function(txt) {
        return txt.replace(_newlineRegex, "
");
    };

    moment.lang("en", {
        relativeTime : {
            // our custom values
            s  : "%ds",
            m  : "1m",
            mm : "%dm",
            h  : "1h",
            hh : "%dh",

            // default moment.js values
            future : "in %s",
            past   : "%s ago",
            d      : "a day",
            dd     : "%d days",
            M      : "a month",
            MM     : "%d months",
            y      : "a year",
            yy     : "%d years"
        }
    });

    Timeline = Y.Base.create("timeline", Y.View, [
        extensions.TimelineMenus,
        extensions.TweetActions
    ], {
        template : templates.timeline,

        initializer : function() {
            var model = this.get("model");

            this._handles = [
                model.after("reset", this.render, this),
                model.get("tweets").after([ "reset", "add", "more" ], this._renderUpdate, this)
            ];
        },

        destructor : function() {
            new Y.EventTarget(this._handles).detach();

            this._handles = null;
        },

        render : function() {
            var timeline = this.get("model").toJSON();

            this.get("container").setHTML(
                this.template(
                    Y.merge(
                        timeline,
                        {
                            tweets : this._renderTweets(timeline.tweets),
                            _t     : templates
                        }
                    )
                )
            );

            this.rendered = true;

            return this;
        },

        _renderUpdate : function(e) {
            var list, now, models, updates;

            if(!this.rendered) {
                return this.render();
            }

            models  = e.models || e.parsed || [ e.model ];
            updates = models.length;

            list = this.get("container").one(".tweets");
            list.prepend(
                this._renderTweets(models)
            );

            if(updates === this.get("model").get("tweets").size()) {
                return;
            }

            now = moment();

            // Update timestamps for all other tweets
            this.get("model").get("tweets").each(function(tweet, idx) {
                var el;

                // skip the models we just rendered
                if(idx < updates) {
                    return;
                }

                el = list.one("[data-id='" + tweet.id_str + "'] .time");
                el.setHTML(this._tweetDate(now, tweet));
            }.bind(this));
        },

        _renderTweets : function(tweets) {
            var self = this,
                now  = moment();

            return tweets.reduce(function(prev, tweet) {
                var details = tweet.retweeted_status || tweet;

                return prev + templates.tweet({
                    _t      : templates,
                    tweet   : tweet,
                    details : details,
                    date    : self._tweetDate(now, tweet),
                    html    : text.autoLinkWithJSON(
                                _nl2br(details.text),
                                details.entities,
                                _options
                    )
                });
            }, "");
        },

        _tweetDate : function(now, tweet) {
            var time = moment(tweet.created_at),
                diff = now.diff(time, "hours");

            // TODO: .fromNow is a little over-eager about showing "1 day", should figure out why
            return (diff > 24) ? time.format("DD MMM") : time.fromNow(true);
        }
    });

    Y.namespace("Falco.Views").Timeline = Timeline;

}, "@VERSION@", {
    requires : [
        // YUI
        "base-build",
        "view",

        // Extensions
        "extension-timeline-menus",
        "extension-tweet-actions",

        // Templates
        "template-timeline",
        "template-tweet",
        "template-tweet-name",

        // CSS
        "css-timeline",
        "css-tweet",
        "css-icons"
    ]
});
<commit_msg>Maintain scrolling position when loading new items<commit_after>YUI.add("view-timeline", function(Y) {
    "use strict";

    var moment     = require("moment"),
        text       = require("twitter-text"),

        falco      = Y.namespace("Falco"),
        extensions = Y.namespace("Falco.Extensions"),
        templates  = Y.namespace("Falco.Templates"),

        _options, _newlineRegex, _nl2br, Timeline;

    _options = {
        "data-external" : ""
    };

    _newlineRegex = /(?:\r\n|\n|\r)/g;
    _nl2br = function(txt) {
        return txt.replace(_newlineRegex, "
");
    };

    moment.lang("en", {
        relativeTime : {
            // our custom values
            s  : "%ds",
            m  : "1m",
            mm : "%dm",
            h  : "1h",
            hh : "%dh",

            // default moment.js values
            future : "in %s",
            past   : "%s ago",
            d      : "a day",
            dd     : "%d days",
            M      : "a month",
            MM     : "%d months",
            y      : "a year",
            yy     : "%d years"
        }
    });

    Timeline = Y.Base.create("timeline", Y.View, [
        extensions.TimelineMenus,
        extensions.TweetActions
    ], {
        template : templates.timeline,

        initializer : function() {
            var model = this.get("model");

            this._handles = [
                model.after("reset", this.render, this),
                model.get("tweets").after([ "reset", "add", "more" ], this._renderUpdate, this)
            ];
        },

        destructor : function() {
            new Y.EventTarget(this._handles).detach();

            this._handles = null;
        },

        render : function() {
            var timeline = this.get("model").toJSON();

            this.get("container").setHTML(
                this.template(
                    Y.merge(
                        timeline,
                        {
                            tweets : this._renderTweets(timeline.tweets),
                            _t     : templates
                        }
                    )
                )
            );

            this.rendered = true;

            return this;
        },

        _renderUpdate : function(e) {
            var container, list, models, now, updates, scrolled;

            if(!this.rendered) {
                return this.render();
            }

            models  = e.models || e.parsed || [ e.model ];
            updates = models.length;

            container = this.get("container");
            list      = container.one(".tweets");

            scrolled = container.get("scrollHeight") - container.get("scrollTop");

            list.prepend(
                this._renderTweets(models)
            );

            if(scrolled) {
                container.set("scrollTop", container.get("scrollHeight") - scrolled);
            }

            if(updates === this.get("model").get("tweets").size()) {
                return;
            }

            now = moment();

            // Update timestamps for all other tweets
            this.get("model").get("tweets").each(function(tweet, idx) {
                var el;

                // skip the models we just rendered
                if(idx < updates) {
                    return;
                }

                el = list.one("[data-id='" + tweet.id_str + "'] .time");
                el.setHTML(this._tweetDate(now, tweet));
            }.bind(this));
        },

        _renderTweets : function(tweets) {
            var self = this,
                now  = moment();

            return tweets.reduce(function(prev, tweet) {
                var details = tweet.retweeted_status || tweet;

                return prev + templates.tweet({
                    _t      : templates,
                    tweet   : tweet,
                    details : details,
                    date    : self._tweetDate(now, tweet),
                    html    : text.autoLinkWithJSON(
                                _nl2br(details.text),
                                details.entities,
                                _options
                    )
                });
            }, "");
        },

        _tweetDate : function(now, tweet) {
            var time = moment(tweet.created_at),
                diff = now.diff(time, "hours");

            // TODO: .fromNow is a little over-eager about showing "1 day", should figure out why
            return (diff > 24) ? time.format("DD MMM") : time.fromNow(true);
        }
    });

    Y.namespace("Falco.Views").Timeline = Timeline;

}, "@VERSION@", {
    requires : [
        // YUI
        "base-build",
        "view",

        // Extensions
        "extension-timeline-menus",
        "extension-tweet-actions",

        // Templates
        "template-timeline",
        "template-tweet",
        "template-tweet-name",

        // CSS
        "css-timeline",
        "css-tweet",
        "css-icons"
    ]
});
<|endoftext|>


<commit_before>var inherits = require('../../utils/inherits');
var One = require('../One');

var Cliper = function(options) {
    One.apply(this, arguments);
};

var p = inherits(Cliper, One);

p.draw = function(context) {
    var width = this._state.width;
    var height = this._state.height;
    context.beginPath();
    context.rect(0,0,width,height);
    context.clip();
    context.closePath();
};

module.exports = Cliper;
<commit_msg>level up Cliper<commit_after>var inherits = require('../../utils/inherits');
var One = require('../One');

var Cliper = function(options) {
    One.apply(this, arguments);
};

var p = inherits(Cliper, One);

p.draw = function(context) {
    var width = this._state.width;
    var height = this._state.height;
    var startX = this._state.startX;
    var startY = this._state.startY;
    context.beginPath();
    context.rect(startX,startY,width,height);
    context.clip();
    context.closePath();
};

module.exports = Cliper;
<|endoftext|>


<commit_before>/*
 * BSD 3-Clause License
 *
 * Copyright (c) 2017, MapCreator
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 *  Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 *  Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import {isParentOf} from '../utils/reflection';
import CrudBase from './base/CrudBase';
import JobResult from './JobResult';
import JobShare from './JobShare';
import Layer from './Layer';

export default class JobRevision extends CrudBase {
  get baseUrl() {
    return `/jobs/${this.jobId}/revisions`;
  }

  get resourcePath() {
    return '/jobs/{job_id}/revisions/{id}';
  }

  get resourceName() {
    return 'job-revisions';
  }

  /**
   * Get layers
   * @returns {SimpleResourceProxy} - A proxy for accessing the resource
   */
  get layers() {
    return this._proxyResourceList(Layer);
  }

  /**
   * Get the job result
   * @returns {Promise} - Resolves with a {@link JobResult} instance and rejects with {@link ApiError}
   */
  result() {
    const url = `${this.url}/result`;

    return new Promise((resolve, reject) => {
      this.api.request(url)
        .catch(reject)
        .then(data => resolve(new JobResult(this.api, data)));
    });
  }

  /**
   * Get a result proxy
   *
   * @returns {JobResult} - Empty job result used for
   */
  get resultProxy() {
    const data = {
      jobId: this.jobId,
      jobRevisionId: this.id,
    };

    return new JobResult(this.api, data);
  }

  // noinspection JSCheckFunctionSignatures
  /**
   * Save updated job revision
   * @param {Object} object - Map object
   * @param {Array<Layer>|Array<Number>|null} layers - Array containing all layers for this revision. If set to null the same layers will be used
   * @returns {Promise} - Resolves with a new {@link JobRevision} instance and rejects with {@link ApiError}
   * @throws TypeError
   */
  save(object = {}, layers = null) {
    if (layers && layers.length > 0) {
      if (isParentOf(Layer, layers[0])) {
        layers = layers.map(layer => layer.id);
      } else if (typeof layers[0] !== 'number') {
        throw new TypeError('layers property is not of type Array<Layer>, Array<Number> or null');
      }
    }

    const data = {
      'object': JSON.stringify(object),
      'language_code': this.languageCode,
      'mapstyle_set_id': this.mapstyleSetId,
    };

    if (layers) {
      data.layers = layers;
    }

    return new Promise((resolve, reject) => {
      this.api.request(this.baseUrl, 'POST', data)
        .catch(reject)
        .then(data => resolve(new JobRevision(this.api, data)));
    });
  }

  /**
   * Get job object
   * @returns {Promise} - Resolves with {@link Object} instance containing the map object and rejects with {@link ApiError}
   * @todo document object format
   */
  object() {
    const url = `${this.url}/object`;

    return this.api.request(url);
  }

  /**
   * Build the revision
   * @param {String} callbackUrl - Optional callback url for when the job completes
   * @returns {Promise} - Resolves with an empty {@link Object} and rejects with {@link ApiError}
   */
  build(callbackUrl) {
    const url = `${this.url}/build`;
    const data = {callback: callbackUrl};

    return this.api.request(url, 'POST', data);
  }

  /**
   * Cancels a running job
   * @returns {Promise} - Resolves with an empty {@link Object} and rejects with {@link ApiError}
   */
  cancel() {
    const url = `${this.url}/cancel`;

    return this.api.request(url, 'POST');
  }

  /**
   * Share the job revision
   * @param {String} visibility - See {@link JobShareVisibility}, either `private` or `organisation`
   * @returns {Promise} - Resolves with a {@link String} containing the share link and rejects with {@link ApiError}
   */
  share(visibility = JobShare.visibility.PRIVATE) {
    visibility = visibility.toLowerCase();

    if (visibility !== JobShare.visibility.ORGANISATION &&
      visibility !== JobShare.visibility.PRIVATE) {
      throw new Error(`Unknown visibility '${visibility}'`);
    }

    const url = `${this.url}/share`;

    return this.api.request(url, 'POST', {visibility});
  }
}
<commit_msg>Change JobRevision::resourcePath<commit_after>/*
 * BSD 3-Clause License
 *
 * Copyright (c) 2017, MapCreator
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 *  Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 *  Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import {isParentOf} from '../utils/reflection';
import CrudBase from './base/CrudBase';
import JobResult from './JobResult';
import JobShare from './JobShare';
import Layer from './Layer';

export default class JobRevision extends CrudBase {
  get baseUrl() {
    return `/jobs/${this.jobId}/revisions`;
  }

  get resourcePath() {
    return '/jobs/{job_id}/revisions/{revision}';
  }

  get resourceName() {
    return 'job-revisions';
  }

  /**
   * Get layers
   * @returns {SimpleResourceProxy} - A proxy for accessing the resource
   */
  get layers() {
    return this._proxyResourceList(Layer);
  }

  /**
   * Get the job result
   * @returns {Promise} - Resolves with a {@link JobResult} instance and rejects with {@link ApiError}
   */
  result() {
    const url = `${this.url}/result`;

    return new Promise((resolve, reject) => {
      this.api.request(url)
        .catch(reject)
        .then(data => resolve(new JobResult(this.api, data)));
    });
  }

  /**
   * Get a result proxy
   *
   * @returns {JobResult} - Empty job result used for
   */
  get resultProxy() {
    const data = {
      jobId: this.jobId,
      jobRevisionId: this.id,
    };

    return new JobResult(this.api, data);
  }

  // noinspection JSCheckFunctionSignatures
  /**
   * Save updated job revision
   * @param {Object} object - Map object
   * @param {Array<Layer>|Array<Number>|null} layers - Array containing all layers for this revision. If set to null the same layers will be used
   * @returns {Promise} - Resolves with a new {@link JobRevision} instance and rejects with {@link ApiError}
   * @throws TypeError
   */
  save(object = {}, layers = null) {
    if (layers && layers.length > 0) {
      if (isParentOf(Layer, layers[0])) {
        layers = layers.map(layer => layer.id);
      } else if (typeof layers[0] !== 'number') {
        throw new TypeError('layers property is not of type Array<Layer>, Array<Number> or null');
      }
    }

    const data = {
      'object': JSON.stringify(object),
      'language_code': this.languageCode,
      'mapstyle_set_id': this.mapstyleSetId,
    };

    if (layers) {
      data.layers = layers;
    }

    return new Promise((resolve, reject) => {
      this.api.request(this.baseUrl, 'POST', data)
        .catch(reject)
        .then(data => resolve(new JobRevision(this.api, data)));
    });
  }

  /**
   * Get job object
   * @returns {Promise} - Resolves with {@link Object} instance containing the map object and rejects with {@link ApiError}
   * @todo document object format
   */
  object() {
    const url = `${this.url}/object`;

    return this.api.request(url);
  }

  /**
   * Build the revision
   * @param {String} callbackUrl - Optional callback url for when the job completes
   * @returns {Promise} - Resolves with an empty {@link Object} and rejects with {@link ApiError}
   */
  build(callbackUrl) {
    const url = `${this.url}/build`;
    const data = {callback: callbackUrl};

    return this.api.request(url, 'POST', data);
  }

  /**
   * Cancels a running job
   * @returns {Promise} - Resolves with an empty {@link Object} and rejects with {@link ApiError}
   */
  cancel() {
    const url = `${this.url}/cancel`;

    return this.api.request(url, 'POST');
  }

  /**
   * Share the job revision
   * @param {String} visibility - See {@link JobShareVisibility}, either `private` or `organisation`
   * @returns {Promise} - Resolves with a {@link String} containing the share link and rejects with {@link ApiError}
   */
  share(visibility = JobShare.visibility.PRIVATE) {
    visibility = visibility.toLowerCase();

    if (visibility !== JobShare.visibility.ORGANISATION &&
      visibility !== JobShare.visibility.PRIVATE) {
      throw new Error(`Unknown visibility '${visibility}'`);
    }

    const url = `${this.url}/share`;

    return this.api.request(url, 'POST', {visibility});
  }
}
<|endoftext|>


<commit_before>import {Op as op} from "sequelize"

import normalize from "lib/helper/graphql/normalizeParams"
import db from "server/lib/db/connection"

import Post from "server/model/Post"
import User from "server/model/User"
import Tag from "server/model/Tag"
import PostsTags from "server/model/PostsTags"

const getPost = ({args}) => db.transaction(async transaction => {
  const {id, slug} = args

  const post = await Post.findOne({
    where: {[op.or]: [{id}, {slug}]},

    include: [User, {model: Tag, through: PostsTags}],
    transaction,
  })

  if (!post) {
    throw new Error("Can't find a post")
  }

  return post
})

export default getPost |> normalize
<commit_msg>Small fix.<commit_after>import {Op as op} from "sequelize"

import normalize from "lib/helper/graphql/normalizeParams"
import db from "server/lib/db/connection"

import Post from "server/model/Post"
import User from "server/model/User"
import Tag from "server/model/Tag"
import PostsTags from "server/model/PostsTags"

const getPost = ({args}) => db.transaction(async transaction => {
  const {id, slug} = args

  const post = await Post.findOne({
    where: {[op.or]: [{id}, {slug}]},
    include: [User, {model: Tag, through: PostsTags}],

    transaction,
  })

  if (!post) {
    throw new Error("Can't find a post")
  }

  return post
})

export default getPost |> normalize
<|endoftext|>


<commit_before>var User = require('mongoose').model('User');

module.exports = {
    registerUser: function (req, res, callback) {
        var newUser = req.body;

        User.find({ username: newUser.username}).exec(function (err, foundUser) {
            if (err){
                console.log(err);
            }
            else {
                if (foundUser && foundUser.length > 0) {
                    console.log('User already in the database');
                    callback(err, foundUser);
                } else {
                    newUser.dateRegistered = new Date();
                    User.create(newUser, callback);
                    res.send({redirect: '/'});
                }
            }
        });
    },
    getAllUsers: function(req, res, callback) {
        User.find({}).exec(function (err, users) {
            if (err){
                console.log(err);
            }
            else {
                res.send(users);
            }
        })
    },
    getUserById: function(req, res, callback) {
        User.findOne({_id:req.params.id}).exec(function (err, user) {
            if (err){
                console.log(err);
            }
            else {
                res.send(user);
            }
        })
    },
    updateUser: function(req, res, next) {
        if (req.user._id == req.body._id || req.user.roles.indexOf('admin') > -1) {
            var updatedUserData = req.body;
            if (updatedUserData.password && updatedUserData.password.length > 0) {
                updatedUserData.salt = encryption.generateSalt();
                updatedUserData.hashPass = encryption.generateHashedPassword(newUserData.salt, newUserData.password);
            }

            User.update({_id: req.body._id}, updatedUserData, function() {
                res.end();
            })
        }
        else {
            res.send({reason: 'You do not have permissions!'})
        }
    },
};<commit_msg>change user registration<commit_after>var User = require('mongoose').model('User');

module.exports = {
    registerUser: function (req, res) {
        var newUser = req.body;

        User.find({ username: newUser.username}).exec(function (err, foundUser) {
            if (err){
                console.log(err);
            }
            else {
                if (foundUser && foundUser.length > 0) {
                    res.status(400).send('User already in the database');
                } else {
                    newUser.dateRegistered = new Date();
                    User.create(newUser, function(err, user){
                        if(err){
                            res.status(400).send;
                        } else {
                            res.send(user);
                        }
                    });
                }
            }
        });
    },
    getAllUsers: function(req, res, callback) {
        User.find({}).exec(function (err, users) {
            if (err){
                console.log(err);
            }
            else {
                res.send(users);
            }
        })
    },
    getUserById: function(req, res, callback) {
        User.findOne({_id:req.params.id}).exec(function (err, user) {
            if (err){
                console.log(err);
            }
            else {
                res.send(user);
            }
        })
    },
    updateUser: function(req, res, next) {
        if (req.user._id == req.body._id || req.user.roles.indexOf('admin') > -1) {
            var updatedUserData = req.body;
            if (updatedUserData.password && updatedUserData.password.length > 0) {
                updatedUserData.salt = encryption.generateSalt();
                updatedUserData.hashPass = encryption.generateHashedPassword(newUserData.salt, newUserData.password);
            }

            User.update({_id: req.body._id}, updatedUserData, function() {
                res.end();
            })
        }
        else {
            res.send({reason: 'You do not have permissions!'})
        }
    },
};<|endoftext|>


<commit_before>import iterator from './iterator-factory';
import iteratorSymbol from './iterator-symbol';

export default function Iterable(val) {
    this._source = val == null ? this : val;
}

Iterable.prototype[iteratorSymbol] = function () {
    return iterator(this._source);
};

Iterable.prototype.toString = function () {
    return '[Iterable]';
};

Iterable.prototype.valueOf = function () {
    return this._source;
};
<commit_msg>do not save null source<commit_after>import iterator from './iterator-factory';
import iteratorSymbol from './iterator-symbol';

export default function Iterable(source) {
    if (source != null) {
        this._source = source;
    }
}

Iterable.prototype[iteratorSymbol] = function () {
    return iterator(this._source);
};

Iterable.prototype.toString = function () {
    return '[Iterable]';
};

Iterable.prototype.valueOf = function () {
    return this._source == null ? this : this._source;
};
<|endoftext|>