<commit_before>import Declaration from "./declaration"
import {default as Doc, DocTypeNode} from "./doc"
import Parameter from "./parameter"
import Block from "./block"
import Identifier from "./identifier"
import {Context, ContextTypes, ParserStateOption} from "./node"
import * as PHPType from "../php-type"
import * as PHPError from "../php-error"

export default class _Function extends Declaration {
    /** @type {Parameter[]} */
    get arguments() {
        return this.cacheNodeArray("arguments")
    }
    /** @type {?Block} */
    get body() {
        return this.cacheNode("body")
    }
    /** @type {boolean} */
    get byref() {
        return this.node.byref
    }
    /** @type {boolean} */
    get nullable() {
        return this.node.nullable
    }
    /** @type {Identifier} */
    get type() {
        return this.node.type
    }
    /**
     * Checks that syntax seems ok
     * @param {Context} context
     * @param {Set<ParserStateOption.Base>} [parser_state]
     * @param {?Doc} [doc]
     * @returns {?ContextTypes} The set of types applicable to this value
     */
    check(context, parser_state = new Set(), doc = null) {
        super.check(context, parser_state, doc)
        if(!doc) {
            this.throw(new PHPError.NoDoc(), context)
        }
        let doc_function_type
        if(doc) {
            try {
                let doc_structure = doc.structure
                if(
                    doc_structure.some(c => !!c.kind.match(/^(var|param|return)$/))
                ) {
                    let structure_arg_types = []
                    let structure_arg_names = []
                    let structure_return = null
                    doc_structure.forEach(c => c.resolve({
                        param: c => {
                            let param_type = c.typeStructure
                            this.resolveAllDocNames(
                                param_type,
                                context,
                                doc
                            )
                            structure_arg_types.push(param_type)
                            structure_arg_names.push(c.name)
                        },
                        return: c => {
                            let return_type = c.typeStructure
                            this.resolveAllDocNames(
                                return_type,
                                context,
                                doc
                            )
                            structure_return = return_type
                        }
                    }))
                    doc_function_type =
                        new PHPType.Function(structure_arg_types, structure_return)
                }
            } catch(e) {
                this.throw(
                    new PHPError.BadDoc(`Doc parse failure: ${e.message}`),
                    context,
                    doc.loc
                )
            }
        }
        var inner_context = context.childContext()

        let arg_types = []
        let pass_by_reference_positions = {}
        this.arguments.forEach(
            (node, index) => {
                arg_types.push(node.check(inner_context, parser_state, null).expressionType)
                if(node.byref) {
                    pass_by_reference_positions[index] = true
                }
            }
        )
        if(context.findName("$this")) {
            inner_context.setThis()
        }

        let signature_type
        if(this.type) {
            signature_type = PHPType.Core.named(context.resolveName(this.type.name, this.type.resolution))
            if(this.nullable) {
                signature_type = signature_type.addTypesFrom(PHPType.Core.types.null)
            }
        }
        let return_type
        if(this.body) {
            return_type = this.body.check(inner_context, new Set(), null).returnType
            if(signature_type && !return_type.compliesWith(signature_type)) {
                this.throw(new PHPError.ReturnTypeMismatch(
                    `Practical return type ${return_type} does not match signature ${signature_type}`
                ), context)
            }
        } else if(signature_type) {
            return_type = signature_type
        } else {
            return_type = PHPType.Core.types.mixed
        }
        let function_type = new PHPType.Function(
            arg_types,
            return_type,
            pass_by_reference_positions
        )
        if(
            doc_function_type &&
            !function_type.compliesWith(doc_function_type)
        ) {
            this.throw(
                new PHPError.BadDoc(
                    `Practical type ${function_type} does not comply with documented type ${doc_function_type} for ${this.name}`
                ),
                context
            )
        }
        if(context.classContext && context.classContext.name == "\\Slim\\App") {
            switch(this.name) {
                case "group":
                    function_type.callbackPositions[1] = PHPType.Core.named("\\Slim\\App")
                    break
                default:
            }
        }
        let types = function_type.union
        if(this.constructor === _Function) {
            context.addName(this.name, types)
        }
        return new ContextTypes(types) // Special case
    }
}
<commit_msg>Prefer the documented function type if the return type is unrecognised<commit_after>import Declaration from "./declaration"
import {default as Doc, DocTypeNode} from "./doc"
import Parameter from "./parameter"
import Block from "./block"
import Identifier from "./identifier"
import {Context, ContextTypes, ParserStateOption} from "./node"
import * as PHPType from "../php-type"
import * as PHPError from "../php-error"

export default class _Function extends Declaration {
    /** @type {Parameter[]} */
    get arguments() {
        return this.cacheNodeArray("arguments")
    }
    /** @type {?Block} */
    get body() {
        return this.cacheNode("body")
    }
    /** @type {boolean} */
    get byref() {
        return this.node.byref
    }
    /** @type {boolean} */
    get nullable() {
        return this.node.nullable
    }
    /** @type {Identifier} */
    get type() {
        return this.node.type
    }
    /**
     * Checks that syntax seems ok
     * @param {Context} context
     * @param {Set<ParserStateOption.Base>} [parser_state]
     * @param {?Doc} [doc]
     * @returns {?ContextTypes} The set of types applicable to this value
     */
    check(context, parser_state = new Set(), doc = null) {
        super.check(context, parser_state, doc)
        if(!doc) {
            this.throw(new PHPError.NoDoc(), context)
        }
        let doc_function_type
        if(doc) {
            try {
                let doc_structure = doc.structure
                if(
                    doc_structure.some(c => !!c.kind.match(/^(var|param|return)$/))
                ) {
                    let structure_arg_types = []
                    let structure_arg_names = []
                    let structure_return = null
                    doc_structure.forEach(c => c.resolve({
                        param: c => {
                            let param_type = c.typeStructure
                            this.resolveAllDocNames(
                                param_type,
                                context,
                                doc
                            )
                            structure_arg_types.push(param_type)
                            structure_arg_names.push(c.name)
                        },
                        return: c => {
                            let return_type = c.typeStructure
                            this.resolveAllDocNames(
                                return_type,
                                context,
                                doc
                            )
                            structure_return = return_type
                        }
                    }))
                    doc_function_type =
                        new PHPType.Function(structure_arg_types, structure_return)
                }
            } catch(e) {
                this.throw(
                    new PHPError.BadDoc(`Doc parse failure: ${e.message}`),
                    context,
                    doc.loc
                )
            }
        }
        var inner_context = context.childContext()

        let arg_types = []
        let pass_by_reference_positions = {}
        this.arguments.forEach(
            (node, index) => {
                arg_types.push(node.check(inner_context, parser_state, null).expressionType)
                if(node.byref) {
                    pass_by_reference_positions[index] = true
                }
            }
        )
        if(context.findName("$this")) {
            inner_context.setThis()
        }

        let signature_type
        if(this.type) {
            signature_type = PHPType.Core.named(context.resolveName(this.type.name, this.type.resolution))
            if(this.nullable) {
                signature_type = signature_type.addTypesFrom(PHPType.Core.types.null)
            }
        }
        let return_type
        if(this.body) {
            return_type = this.body.check(inner_context, new Set(), null).returnType
            if(signature_type && !return_type.compliesWith(signature_type)) {
                this.throw(new PHPError.ReturnTypeMismatch(
                    `Practical return type ${return_type} does not match signature ${signature_type}`
                ), context)
            }
        } else if(signature_type) {
            return_type = signature_type
        } else {
            return_type = PHPType.Core.types.mixed
        }
        let function_type = new PHPType.Function(
            arg_types,
            return_type,
            pass_by_reference_positions
        )
        if(
            doc_function_type &&
            !function_type.compliesWith(doc_function_type)
        ) {
            this.throw(
                new PHPError.BadDoc(
                    `Practical type ${function_type} does not comply with documented type ${doc_function_type} for ${this.name}`
                ),
                context
            )
        }
        if(context.classContext && context.classContext.name == "\\Slim\\App") {
            switch(this.name) {
                case "group":
                    function_type.callbackPositions[1] = PHPType.Core.named("\\Slim\\App")
                    break
                default:
            }
        }
        let types = function_type.returnType.isMixed ?
            (doc_function_type || function_type).union :
            function_type.union
        if(this.constructor === _Function) {
            context.addName(this.name, types)
        }
        return new ContextTypes(types) // Special case
    }
}
<|endoftext|>


<commit_before>var page = tabris.create("Page", {
  title: "Storing data on the device",
  topLevel: true
});

var keyTextView = tabris.create("TextView", {
  layoutData: {left: 10, top: 20},
  text: "Key:"
}).appendTo(page);

var keyField = tabris.create("TextInput", {
  layoutData: {left: 60, baseline: keyTextView, right: 10},
  text: "foo"
}).appendTo(page);

var valueTextView = tabris.create("TextView", {
  layoutData: {left: 10, top: [keyField, 20]},
  text: "Value:"
}).appendTo(page);

var valueField = tabris.create("TextInput", {
  layoutData: {left: 60, baseline: valueTextView, right: 10},
  text: localStorage.getItem("foo") || "bar"
}).appendTo(page);

tabris.create("Button", {
  layoutData: {left: 10, right: ["66%", 5], top: [valueTextView, 20]},
  text: "Set"
}).on("select", function() {
  if (!keyField.get("text")) {
    console.error("They key cannot be empty.");
  } else if (!valueField.get("text")) {
    console.error("They value cannot be empty.");
  } else {
    localStorage.setItem(keyField.get("text"), valueField.get("text"));
    valueField.set("text", "");
  }
}).appendTo(page);

tabris.create("Button", {
  layoutData: {left: ["33%", 5], right: ["33%", 5], top: [valueTextView, 20]},
  text: "Get"
}).on("select", function() {
  if (!keyField.get("text")) {
    console.error("The key cannot be empty.");
  } else {
    valueField.set("text", "");
    valueField.set("text", localStorage.getItem(keyField.get("text")));
  }
}).appendTo(page);

tabris.create("Button", {
  layoutData: {left: ["66%", 5], right: 10, top: [valueTextView, 20]},
  text: "Remove"
}).on("select", function() {
  localStorage.removeItem(keyField.get("text"));
  valueField.set("text", "");
}).appendTo(page);

page.open();
<commit_msg>Fix a typo in local-storage example<commit_after>var page = tabris.create("Page", {
  title: "Storing data on the device",
  topLevel: true
});

var keyTextView = tabris.create("TextView", {
  layoutData: {left: 10, top: 20},
  text: "Key:"
}).appendTo(page);

var keyField = tabris.create("TextInput", {
  layoutData: {left: 60, baseline: keyTextView, right: 10},
  text: "foo"
}).appendTo(page);

var valueTextView = tabris.create("TextView", {
  layoutData: {left: 10, top: [keyField, 20]},
  text: "Value:"
}).appendTo(page);

var valueField = tabris.create("TextInput", {
  layoutData: {left: 60, baseline: valueTextView, right: 10},
  text: localStorage.getItem("foo") || "bar"
}).appendTo(page);

tabris.create("Button", {
  layoutData: {left: 10, right: ["66%", 5], top: [valueTextView, 20]},
  text: "Set"
}).on("select", function() {
  if (!keyField.get("text")) {
    console.error("The key cannot be empty.");
  } else if (!valueField.get("text")) {
    console.error("The value cannot be empty.");
  } else {
    localStorage.setItem(keyField.get("text"), valueField.get("text"));
    valueField.set("text", "");
  }
}).appendTo(page);

tabris.create("Button", {
  layoutData: {left: ["33%", 5], right: ["33%", 5], top: [valueTextView, 20]},
  text: "Get"
}).on("select", function() {
  if (!keyField.get("text")) {
    console.error("The key cannot be empty.");
  } else {
    valueField.set("text", "");
    valueField.set("text", localStorage.getItem(keyField.get("text")));
  }
}).appendTo(page);

tabris.create("Button", {
  layoutData: {left: ["66%", 5], right: 10, top: [valueTextView, 20]},
  text: "Remove"
}).on("select", function() {
  localStorage.removeItem(keyField.get("text"));
  valueField.set("text", "");
}).appendTo(page);

page.open();
<|endoftext|>


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

var htmlProducerFactory = require("./htmlProducer");
var url = require("url");
var path = require("path");
var fs = require("fs");
var screenies = require("./screenies");
var utils = require("./utils");
var w3c = require('w3c-validate').createValidator();
var http = require('http');

var logger = utils.createLogger({sourceFilePath : __filename});

function ProjectCommands(args) {
    var composer, project, runtime;
    var runningScreenshotsGen = false;
    var runningValidation = false;

    var createHtmlProducer = function () {
        return htmlProducerFactory.createHtmlProducer({
            runtime:runtime
        });
    };

    var commandFactory = {
        "list-all": function (request, response, project) {
            var files = project.listAllTemplatePaths();
            var hp = createHtmlProducer();
            var out = hp.createListingMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html"
                },
                content: out
            };
        },
        "list-compiled": function (request, response, project) {
            var files = project.listCompiledTemplatePaths();
            files.sort();
            var hp = createHtmlProducer(project);
            var out = hp.createListingMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html"
                },
                content: out
            };
        },
        "generate-compiled-nav": function (request, response, project) {
            var files = project.listCompiledTemplatePaths();
            files.sort();
            var hp = createHtmlProducer(project);
            var out = hp.createBareListingEntriesMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html"
                },
                content: out
            };
        },
        "list-referencing": function (request, response, project) {
            var files = project.listPathsWithReferences();
            files.sort();
            var hp = createHtmlProducer(project);
            var out = hp.createListingMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html"
                },
                content: out
            };
        },
        "list-referencing-bare": function (request, response, project) {
            var files = project.listPathsWithReferences();
            files.sort();
            var hp = createHtmlProducer(project);
            var out = hp.createBareListingEntriesMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html"
                },
                content: out
            };
        },
        "list-referenced": function (request, response, project) {
            var files = project.listAllReferencedPaths();
            files.sort();
            var hp = createHtmlProducer(project);
            var out = hp.createListingMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html"
                },
                content: out
            };
        },
        "list": function (request, response, project) {
            var files = project.listAllTemplatePaths();
            files.sort();
            var hp = createHtmlProducer(project);
            var out = hp.createListingMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html"
                },
                content: out
            };
        },
        "compile_all": function (request, response, project) {
            var files = project.listAllTemplatePaths();
            files.forEach(function (filePath) {
                var fileContents = runtime.readFile(filePath);
                var fileName = path.basename(filePath);
                try{
                    var composed = composer.composeTemplate(filePath, fileContents);
                    var responsePath = path.dirname(filePath) + "/" + fileName.substring(0, fileName.lastIndexOf('.')) + '-compiled.html';
                    runtime.writeFile(responsePath, composed.content);
                    logger.info("Wrote compiled version to " + responsePath);
                }catch(CompilationError){
                    logger.error("Could not compile " + fileName + " with contents: " + fileContents);
                    console.trace(CompilationError);
                    logger.warn("Skipping " + fileName + " from back compilation.");
                }
            });
            var hp = createHtmlProducer(project);
            var out = hp.createCompiledMarkup(files) + project.readViewScriptsMarkup();
            project.updateDynamic();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html"
                },
                content: out
            };
        },
        "delete_compiled": function (request, response, project) {
            var files = project.listCompiledTemplatePaths();
            files.forEach(function (fd) {
                var filePath = fd;
                runtime.deleteFile(filePath);
                logger.info("Deleted compiled file : " + filePath);
            });
            project.updateDynamic();
            var hp = createHtmlProducer(project);
            var out = hp.createDeletedMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html"
                },
                content: out
            };
        },
        "generate-components-page": function (request, response, project) {
            var url_parts = url.parse(request.url, true);
            var componentDirsTxt = url_parts.query.componentDirs || false;
            if (!componentDirsTxt) {
                logger.error("No componentDirs argument passed= " + request.url);
                return {
                    status: 406,
                    headers: {
                        "Content-Type": "text/plain"
                    },
                    content: "Missing componentDirs request argument, eg. componentDirs=components,portlets"
                };
            } else {
                var dirs = [componentDirsTxt];
                if (componentDirsTxt.indexOf(',') > 0) {
                    dirs = componentDirsTxt.split(',');
                }
                var paths = [];
                dirs.forEach(function (dir) {
                    var pd = project.resolveProjectFile(dir);
                    var templatePaths = project.listProjectTemplatePaths(pd);
                    templatePaths.forEach(function (tp) {
                        paths.push(tp);
                    });
                });
                paths.sort();
                var parentDivClasses = url_parts.query.parentDivClasses || "col-md-6";
                var out = "";
                paths.forEach(function (p) {
                    logger.info("Processing ", p);
                    var composed = composer.composeTemplate(path.basename(p), runtime.readFile(p));
                    out += '
' + composed.content + '
';
                });
                project.writeDynamicFile('components-page.html', out);
                return {
                    status: 302,
                    headers: {
                        "Content-Type": "text/html",
                        "Location": "/components-generated.html"
                    },
                    content: out
                };
            }
        },
        "exit": function (request, response) {
            logger.info("Handling exit request received by browser!");
            response.writeHead(200, {
                "Content-Type": "text/html"
            });
            response.on("finish", function () {
                logger.info("Finished response, exiting protostar.");
                process.exit(0);
            });
            response.write("
Protostar is exiting by your command, bye bye!
");
            response.end();
            return false;
        },
        "validate": function (request, response) {

            if (runningValidation) {
                logger.info("Still running screenshotgen");
                response.writeHead(302, {
                    "Location": "http://" + request.headers.host
                });
                response.end();
                return false;
            }
            runningValidation = true;

            var allTemplatePaths = project.listAllTemplatePaths();

            logger.info("Validating " + allTemplatePaths.length  + " pages...");
            var urlErrors = {};
            function removeWrite(templatePaths) {
                if (templatePaths.length < 1) {
                    logger.info("All are empty");
                    return;
                }
                var templatePath = templatePaths[0];
                templatePaths.splice(0, 1);

                var templateUrlPath = runtime.createUrlPathForFile(templatePath);
                var options = {
                    host: (process.env.VCAP_APP_HOST || 'localhost'),
                    port: (process.env.VCAP_APP_PORT || 8888),
                    path: templateUrlPath
                };

                var createUrlErrorsMarkup = function(urlErrors){
                    var out = '<!doctype html>
W3C Markup validation errors
';

                    Object.keys(urlErrors).forEach(function(url){
                        out += '
';
                        out+='
'+url+'
'
                        var errors = urlErrors[url];
                        if(errors && utils.getObjectType(errors) === 'Array' && errors.length > 0){
                            out+='
';
                            errors.forEach(function(e){
                                out+='
'+ e.error+'

'+ utils.encodeHtmlEntities(e.context)+'

';
                            });
                            out+='
';
                        }else{
                            out += '
Valid!
';
                        }
                        out+= '
';

                    });
                    return out + '';
                };

                var callback = function(valResp) {
                    var str = '';
                    valResp.on('data', function (chunk) {
                        str += chunk;
                    });
                    valResp.on('end', function () {
                        if(runtime.isDebug()){
                            logger.info(str);
                        }
                        w3c.validate(str, function (err) {
                            logger.info("FINISHED VALIDATING " + templateUrlPath, arguments);
                            if (err) {
                                logger.info("Errors for " + templateUrlPath +": ", err);
                                urlErrors[templateUrlPath] = err;
                            } else {
                                logger.info(templateUrlPath + ' is valid!');
                                urlErrors[templateUrlPath] = "ok";
                            }
                            if (allTemplatePaths.length < 1) {
                                runningValidation = false;
                                response.writeHead(200, {
                                    "Content-Type":"text/html"
                                });
                                logger.info("FOUND errors: ", urlErrors);
                                response.write(createUrlErrorsMarkup(urlErrors));
                                response.end();
                            } else {
                                logger.info("Waiting 1500msec before next ...");
                                setTimeout(function(){
                                    logger.info("Invoking");
                                    removeWrite(allTemplatePaths);
                                }, 2000);

                            }
                        });
                    });
                };
                http.request(options, callback).end();
            }
            removeWrite(allTemplatePaths);
            return false;
        },
        "create": function (request, response, project) {
            var url_parts = url.parse(request.url, true);
            var urlPathname = url_parts.pathname;
            var err = 0;
            var template, templatePath;
            if(!runtime.isExistingProjectFilePath(urlPathname.substring(1))){
                logger.info("pathname doesn't exist : " + urlPathname);
                templatePath = url_parts.query.templatePath;
                logger.info("template path = " + templatePath);
                if (runtime.isProjectFileUrlPathname(templatePath)) {
                    template = runtime.readProjectFile(templatePath);
                    var targetPath = runtime.constructProjectPath(urlPathname.substring(1));
                    project.writeFile(targetPath, template);
                    logger.info("Copied " + templatePath + " to " + targetPath);
                } else {
                    err = "Non existing path " + templatePath;
                }
            }else{
                err = "Refusing to create file at exising path: " + urlPathname;
            }
            var out;
            if (err) {
                out = {
                    status: 406,
                    headers: {
                        "Content-Type": "text/plain"
                    },
                    content: err
                };
            } else {
                out = {
                    status: 302,
                    headers: {
                        "Location": "http://" + request.headers.host + urlPathname
                    }
                };
            }
            return out;
        },
        "screenshot-all": function (request, response, project) {
            if (runningScreenshotsGen) {
                logger.info("Still running screenshotgen");
                response.writeHead(302, {
                    "Location": "http://" + request.headers.host
                });
                response.end();
                return false;
            }
            runningScreenshotsGen = true;
            var sizes = {
                smartphone: {
                    width: 320,
                    height: 480
                },
                tablet: {
                    width: 1024,
                    height: 768
                },
                desktop: {
                    width: 1920,
                    height: 1200
                },
                hires: {
                    width: 2880,
                    height: 1800
                }
            };

            function listSizeNames() {
                var sizeNames = [];
                for (var sn in sizes) {
                    if (sizes.hasOwnProperty(sn)) {
                        sizeNames.push(sn);
                    }
                }
                return sizeNames;
            }

            var allSizeNames = listSizeNames();
            var allTemplatePaths = project.listAllTemplatePaths();
            logger.info("AllTemplatePaths: ", allTemplatePaths);
            var cmds = [];
            allSizeNames.forEach(function (sn) {
                allTemplatePaths.forEach(function (tp) {
                    cmds.push({
                        sizeName: sn,
                        path: tp
                    });
                })
            });

            function removeWrite(cmds, dirName) {
                if (cmds.length < 1) {
                    logger.info("All are empty");
                    return;
                }
                var cmd = cmds[0];
                cmds.splice(0, 1);
                var tp = cmd.path;
                var sizeName = cmd.sizeName;
                var tpName = runtime.createUrlPathForFile(tp);
                logger.info("Creating screenshot for " + tpName + " in " + dirName + " for size " + sizeName);

                var screenieName = tpName.substring(1, tpName.lastIndexOf('.')).replace(new RegExp("\\/", 'g'), "__");
                var imageFilename = screenieName + ".png";
                var screeniePath = project.resolveProjectFile("screenshots/" + dirName + "/" + sizeName + "/" + imageFilename);
                utils.ensureParentDirExists(screeniePath);

                screenies.createScreenshotAdvanced("http://localhost:" + (process.env.VCAP_APP_PORT || 8888) + tpName, screeniePath, sizes[sizeName].width, sizes[sizeName].height, function (imagePath) {
                    logger.info("Saved to " + imagePath);
                    if (cmds.length < 1) {
                        runningScreenshotsGen = false;
                        response.writeHead(302, {
                            "Location": "http://" + request.headers.host
                        });
                        response.end();
                    } else {
                        removeWrite(cmds, dirName);
                    }
                });
            }
            var ts = "" + new Date().getTime();
            var screenshotsDirName = "all_" + ts;
            removeWrite(cmds, screenshotsDirName);
            return false;
        }
    };

    this.getCommandNames = function(){
        var names = [];
        for(var nm in commandFactory){
            if(commandFactory.hasOwnProperty(nm) && typeof commandFactory[nm] === 'function'){
                names.push(nm);
            }
        }
        names.sort();
        return names;
    };

    var parseArgs = function (args) {
        runtime = args.runtime;
        composer = args.composer;
        project = args.project;
    };
    parseArgs(args);
    this.handleCommandRequest = function (command, request, response) {
        logger.info("Running command " + command);
        var responseObj = (commandFactory[command])(request, response, project);
        if(runtime.isDebug()){
            logger.info("Ran command " + command + ":", responseObj);
        }else{
            logger.info("Ran command " + command);
        }
        return responseObj;
    }
}

module.exports = {
    createProjectCommandHandler: function (args) {
        return new ProjectCommands(args);
    },
    getCommandNames: function(){
        var names = [];
        for(var nm in commandFactory){
            if(commandFactory.hasOwnProperty(nm) && typeof commandFactory[nm] === 'function'){
                names.push(nm);
            }
        }
        names.sort();
        return names;
    }
};

<commit_msg>Set char encoding for output to utf-8<commit_after>/**
 * Copyright 2014 IBM Corp.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

var htmlProducerFactory = require("./htmlProducer");
var url = require("url");
var path = require("path");
var fs = require("fs");
var screenies = require("./screenies");
var utils = require("./utils");
var w3c = require('w3c-validate').createValidator();
var http = require('http');

var logger = utils.createLogger({sourceFilePath : __filename});

function ProjectCommands(args) {
    var composer, project, runtime;
    var runningScreenshotsGen = false;
    var runningValidation = false;

    var createHtmlProducer = function () {
        return htmlProducerFactory.createHtmlProducer({
            runtime:runtime
        });
    };

    var commandFactory = {
        "list-all": function (request, response, project) {
            var files = project.listAllTemplatePaths();
            var hp = createHtmlProducer();
            var out = hp.createListingMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html; charset=utf-8"
                },
                content: out
            };
        },
        "list-compiled": function (request, response, project) {
            var files = project.listCompiledTemplatePaths();
            files.sort();
            var hp = createHtmlProducer(project);
            var out = hp.createListingMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html; charset=utf-8"
                },
                content: out
            };
        },
        "generate-compiled-nav": function (request, response, project) {
            var files = project.listCompiledTemplatePaths();
            files.sort();
            var hp = createHtmlProducer(project);
            var out = hp.createBareListingEntriesMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html; charset=utf-8"
                },
                content: out
            };
        },
        "list-referencing": function (request, response, project) {
            var files = project.listPathsWithReferences();
            files.sort();
            var hp = createHtmlProducer(project);
            var out = hp.createListingMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html; charset=utf-8"
                },
                content: out
            };
        },
        "list-referencing-bare": function (request, response, project) {
            var files = project.listPathsWithReferences();
            files.sort();
            var hp = createHtmlProducer(project);
            var out = hp.createBareListingEntriesMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html; charset=utf-8"
                },
                content: out
            };
        },
        "list-referenced": function (request, response, project) {
            var files = project.listAllReferencedPaths();
            files.sort();
            var hp = createHtmlProducer(project);
            var out = hp.createListingMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html; charset=utf-8"
                },
                content: out
            };
        },
        "list": function (request, response, project) {
            var files = project.listAllTemplatePaths();
            files.sort();
            var hp = createHtmlProducer(project);
            var out = hp.createListingMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html; charset=utf-8"
                },
                content: out
            };
        },
        "compile_all": function (request, response, project) {
            var files = project.listAllTemplatePaths();
            files.forEach(function (filePath) {
                var fileContents = runtime.readFile(filePath);
                var fileName = path.basename(filePath);
                try{
                    var composed = composer.composeTemplate(filePath, fileContents);
                    var responsePath = path.dirname(filePath) + "/" + fileName.substring(0, fileName.lastIndexOf('.')) + '-compiled.html';
                    runtime.writeFile(responsePath, composed.content);
                    logger.info("Wrote compiled version to " + responsePath);
                }catch(CompilationError){
                    logger.error("Could not compile " + fileName + " with contents: " + fileContents);
                    console.trace(CompilationError);
                    logger.warn("Skipping " + fileName + " from back compilation.");
                }
            });
            var hp = createHtmlProducer(project);
            var out = hp.createCompiledMarkup(files) + project.readViewScriptsMarkup();
            project.updateDynamic();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html; charset=utf-8"
                },
                content: out
            };
        },
        "delete_compiled": function (request, response, project) {
            var files = project.listCompiledTemplatePaths();
            files.forEach(function (fd) {
                var filePath = fd;
                runtime.deleteFile(filePath);
                logger.info("Deleted compiled file : " + filePath);
            });
            project.updateDynamic();
            var hp = createHtmlProducer(project);
            var out = hp.createDeletedMarkup(files) + project.readViewScriptsMarkup();
            return {
                status: 200,
                headers: {
                    "Content-Type": "text/html; charset=utf-8"
                },
                content: out
            };
        },
        "generate-components-page": function (request, response, project) {
            var url_parts = url.parse(request.url, true);
            var componentDirsTxt = url_parts.query.componentDirs || false;
            if (!componentDirsTxt) {
                logger.error("No componentDirs argument passed= " + request.url);
                return {
                    status: 406,
                    headers: {
                        "Content-Type": "text/plain"
                    },
                    content: "Missing componentDirs request argument, eg. componentDirs=components,portlets"
                };
            } else {
                var dirs = [componentDirsTxt];
                if (componentDirsTxt.indexOf(',') > 0) {
                    dirs = componentDirsTxt.split(',');
                }
                var paths = [];
                dirs.forEach(function (dir) {
                    var pd = project.resolveProjectFile(dir);
                    var templatePaths = project.listProjectTemplatePaths(pd);
                    templatePaths.forEach(function (tp) {
                        paths.push(tp);
                    });
                });
                paths.sort();
                var parentDivClasses = url_parts.query.parentDivClasses || "col-md-6";
                var out = "";
                paths.forEach(function (p) {
                    logger.info("Processing ", p);
                    var composed = composer.composeTemplate(path.basename(p), runtime.readFile(p));
                    out += '
' + composed.content + '
';
                });
                project.writeDynamicFile('components-page.html', out);
                return {
                    status: 302,
                    headers: {
                        "Content-Type": "text/html; charset=utf-8",
                        "Location": "/components-generated.html"
                    },
                    content: out
                };
            }
        },
        "exit": function (request, response) {
            logger.info("Handling exit request received by browser!");
            response.writeHead(200, {
                "Content-Type": "text/html; charset=utf-8"
            });
            response.on("finish", function () {
                logger.info("Finished response, exiting protostar.");
                process.exit(0);
            });
            response.write("
Protostar is exiting by your command, bye bye!
");
            response.end();
            return false;
        },
        "validate": function (request, response) {

            if (runningValidation) {
                logger.info("Still running screenshotgen");
                response.writeHead(302, {
                    "Location": "http://" + request.headers.host
                });
                response.end();
                return false;
            }
            runningValidation = true;

            var allTemplatePaths = project.listAllTemplatePaths();

            logger.info("Validating " + allTemplatePaths.length  + " pages...");
            var urlErrors = {};
            function removeWrite(templatePaths) {
                if (templatePaths.length < 1) {
                    logger.info("All are empty");
                    return;
                }
                var templatePath = templatePaths[0];
                templatePaths.splice(0, 1);

                var templateUrlPath = runtime.createUrlPathForFile(templatePath);
                var options = {
                    host: (process.env.VCAP_APP_HOST || 'localhost'),
                    port: (process.env.VCAP_APP_PORT || 8888),
                    path: templateUrlPath
                };

                var createUrlErrorsMarkup = function(urlErrors){
                    var out = '<!doctype html>
W3C Markup validation errors
';

                    Object.keys(urlErrors).forEach(function(url){
                        out += '
';
                        out+='
'+url+'
'
                        var errors = urlErrors[url];
                        if(errors && utils.getObjectType(errors) === 'Array' && errors.length > 0){
                            out+='
';
                            errors.forEach(function(e){
                                out+='
'+ e.error+'

'+ utils.encodeHtmlEntities(e.context)+'

';
                            });
                            out+='
';
                        }else{
                            out += '
Valid!
';
                        }
                        out+= '
';

                    });
                    return out + '';
                };

                var callback = function(valResp) {
                    var str = '';
                    valResp.on('data', function (chunk) {
                        str += chunk;
                    });
                    valResp.on('end', function () {
                        if(runtime.isDebug()){
                            logger.info(str);
                        }
                        w3c.validate(str, function (err) {
                            logger.info("FINISHED VALIDATING " + templateUrlPath, arguments);
                            if (err) {
                                logger.info("Errors for " + templateUrlPath +": ", err);
                                urlErrors[templateUrlPath] = err;
                            } else {
                                logger.info(templateUrlPath + ' is valid!');
                                urlErrors[templateUrlPath] = "ok";
                            }
                            if (allTemplatePaths.length < 1) {
                                runningValidation = false;
                                response.writeHead(200, {
                                    "Content-Type":"text/html; charset=utf-8"
                                });
                                logger.info("FOUND errors: ", urlErrors);
                                response.write(createUrlErrorsMarkup(urlErrors));
                                response.end();
                            } else {
                                logger.info("Waiting 1500msec before next ...");
                                setTimeout(function(){
                                    logger.info("Invoking");
                                    removeWrite(allTemplatePaths);
                                }, 2000);

                            }
                        });
                    });
                };
                http.request(options, callback).end();
            }
            removeWrite(allTemplatePaths);
            return false;
        },
        "create": function (request, response, project) {
            var url_parts = url.parse(request.url, true);
            var urlPathname = url_parts.pathname;
            var err = 0;
            var template, templatePath;
            if(!runtime.isExistingProjectFilePath(urlPathname.substring(1))){
                logger.info("pathname doesn't exist : " + urlPathname);
                templatePath = url_parts.query.templatePath;
                logger.info("template path = " + templatePath);
                if (runtime.isProjectFileUrlPathname(templatePath)) {
                    template = runtime.readProjectFile(templatePath);
                    var targetPath = runtime.constructProjectPath(urlPathname.substring(1));
                    project.writeFile(targetPath, template);
                    logger.info("Copied " + templatePath + " to " + targetPath);
                } else {
                    err = "Non existing path " + templatePath;
                }
            }else{
                err = "Refusing to create file at exising path: " + urlPathname;
            }
            var out;
            if (err) {
                out = {
                    status: 406,
                    headers: {
                        "Content-Type": "text/plain"
                    },
                    content: err
                };
            } else {
                out = {
                    status: 302,
                    headers: {
                        "Location": "http://" + request.headers.host + urlPathname
                    }
                };
            }
            return out;
        },
        "screenshot-all": function (request, response, project) {
            if (runningScreenshotsGen) {
                logger.info("Still running screenshotgen");
                response.writeHead(302, {
                    "Location": "http://" + request.headers.host
                });
                response.end();
                return false;
            }
            runningScreenshotsGen = true;
            var sizes = {
                smartphone: {
                    width: 320,
                    height: 480
                },
                tablet: {
                    width: 1024,
                    height: 768
                },
                desktop: {
                    width: 1920,
                    height: 1200
                },
                hires: {
                    width: 2880,
                    height: 1800
                }
            };

            function listSizeNames() {
                var sizeNames = [];
                for (var sn in sizes) {
                    if (sizes.hasOwnProperty(sn)) {
                        sizeNames.push(sn);
                    }
                }
                return sizeNames;
            }

            var allSizeNames = listSizeNames();
            var allTemplatePaths = project.listAllTemplatePaths();
            logger.info("AllTemplatePaths: ", allTemplatePaths);
            var cmds = [];
            allSizeNames.forEach(function (sn) {
                allTemplatePaths.forEach(function (tp) {
                    cmds.push({
                        sizeName: sn,
                        path: tp
                    });
                })
            });

            function removeWrite(cmds, dirName) {
                if (cmds.length < 1) {
                    logger.info("All are empty");
                    return;
                }
                var cmd = cmds[0];
                cmds.splice(0, 1);
                var tp = cmd.path;
                var sizeName = cmd.sizeName;
                var tpName = runtime.createUrlPathForFile(tp);
                logger.info("Creating screenshot for " + tpName + " in " + dirName + " for size " + sizeName);

                var screenieName = tpName.substring(1, tpName.lastIndexOf('.')).replace(new RegExp("\\/", 'g'), "__");
                var imageFilename = screenieName + ".png";
                var screeniePath = project.resolveProjectFile("screenshots/" + dirName + "/" + sizeName + "/" + imageFilename);
                utils.ensureParentDirExists(screeniePath);

                screenies.createScreenshotAdvanced("http://localhost:" + (process.env.VCAP_APP_PORT || 8888) + tpName, screeniePath, sizes[sizeName].width, sizes[sizeName].height, function (imagePath) {
                    logger.info("Saved to " + imagePath);
                    if (cmds.length < 1) {
                        runningScreenshotsGen = false;
                        response.writeHead(302, {
                            "Location": "http://" + request.headers.host
                        });
                        response.end();
                    } else {
                        removeWrite(cmds, dirName);
                    }
                });
            }
            var ts = "" + new Date().getTime();
            var screenshotsDirName = "all_" + ts;
            removeWrite(cmds, screenshotsDirName);
            return false;
        }
    };

    this.getCommandNames = function(){
        var names = [];
        for(var nm in commandFactory){
            if(commandFactory.hasOwnProperty(nm) && typeof commandFactory[nm] === 'function'){
                names.push(nm);
            }
        }
        names.sort();
        return names;
    };

    var parseArgs = function (args) {
        runtime = args.runtime;
        composer = args.composer;
        project = args.project;
    };
    parseArgs(args);
    this.handleCommandRequest = function (command, request, response) {
        logger.info("Running command " + command);
        var responseObj = (commandFactory[command])(request, response, project);
        if(runtime.isDebug()){
            logger.info("Ran command " + command + ":", responseObj);
        }else{
            logger.info("Ran command " + command);
        }
        return responseObj;
    }
}

module.exports = {
    createProjectCommandHandler: function (args) {
        return new ProjectCommands(args);
    },
    getCommandNames: function(){
        var names = [];
        for(var nm in commandFactory){
            if(commandFactory.hasOwnProperty(nm) && typeof commandFactory[nm] === 'function'){
                names.push(nm);
            }
        }
        names.sort();
        return names;
    }
};

<|endoftext|>


<commit_before>import React, { Fragment } from 'react'
import { withFormik } from 'formik'
import yup from 'yup'
import api from 'api'
import { AutoSaver, Field, Submit } from 'components/Forms'
import { Button, Text, Label } from '@hackclub/design-system'

const InnerForm = ({
  values,
  errors,
  touched,
  handleChange,
  handleBlur,
  handleSubmit,
  isSubmitting
}) => (
  <form onSubmit={handleSubmit}>
    <Field
      label={
        <Fragment>
          Should this event be listed on{' '}

            hackathons.hackclub.com
          ?
        </Fragment>
      }
      name="public"
      value={values.public}
      error={touched.public && errors.public}
      onChange={handleChange}
      onBlur={handleBlur}
      type="select"
    >
      <option value="false">No</option>
      <option value="true">Yes</option>
    </Field>
    <Field
      label="Affiliated with Hack Club"
      name="hack_club_associated"
      value={values.hack_club_associated}
      error={touched.hack_club_associated && errors.hack_club_associated}
      onChange={handleChange}
      onBlur={handleBlur}
      type="select"
    >
      <option value="false">No</option>
      <option value="true">Yes</option>
    </Field>
    <Field
      label="How is it associated"
      name="hack_club_associated_notes"
      value={values.hack_club_associated_notes || ''}
      error={
        touched.hack_club_associated_notes && errors.hack_club_associated_notes
      }
      onChange={handleChange}
      onBlur={handleBlur}
    />
    <Field
      label="Affiliated with MLH"
      name="mlh_associated"
      value={values.mlh_associated}
      error={touched.mlh_associated && errors.mlh_associated}
      onChange={handleChange}
      onBlur={handleBlur}
      type="select"
    >
      <option value="false">No</option>
      <option value="true">Yes</option>
    </Field>
    <Field
      label="Collegiate event"
      name="collegiate"
      value={values.collegiate}
      error={touched.collegiate && errors.collegiate}
      onChange={handleChange}
      onBlur={handleBlur}
      type="select"
    >
      <option value="false">No</option>
      <option value="true">Yes</option>
    </Field>
    <Field
      label="Start date"
      name="start"
      value={values.start || ''}
      error={touched.start && errors.start}
      onChange={handleChange}
      onBlur={handleBlur}
      type="date"
    />
    <Field
      label="End date"
      name="end"
      value={values.end || ''}
      error={touched.end && errors.end}
      onChange={handleChange}
      onBlur={handleBlur}
      type="date"
    />
    <Field
      label="Event Name"
      name="name"
      value={values.name || ''}
      error={touched.name && errors.name}
      onChange={handleChange}
      onBlur={handleBlur}
    />
    <Field
      label="Event Website"
      name="website"
      value={values.website || ''}
      error={touched.website && errors.website}
      onChange={handleChange}
      onBlur={handleBlur}
      placeholder="https://"
    />
    <Field
      label="Total attendance"
      name="total_attendance"
      value={values.total_attendance || ''}
      error={touched.total_attendance && errors.total_attendance}
      onChange={handleChange}
      onBlur={handleBlur}
      type="number"
    />
    <Field
      label="First time hackathon estimate"
      name="first_time_hackathon_estimate"
      value={values.first_time_hackathon_estimate || ''}
      error={
        touched.first_time_hackathon_estimate &&
        errors.first_time_hackathon_estimate
      }
      onChange={handleChange}
      onBlur={handleBlur}
      type="number"
    />
    <Field
      label="Address"
      name="address"
      value={values.address || ''}
      error={touched.address && errors.address}
      onChange={handleChange}
      onBlur={handleBlur}
      type="textarea"
    />
    <Button onClick={handleSubmit}>
      {isSubmitting ? 'Submitting...' : values.id ? 'Update' : 'Create'}
    </Button>
  </form>
)

export default withFormik({
  validationSchema: yup.object().shape({
    public: yup.string().required(),
    hack_club_associated: yup.string().required(),
    hack_club_associated_notes: yup.string().nullable(),
    mlh_associated: yup.string().required(),
    collegiate: yup.string().required(),
    start: yup.date().required(),
    end: yup.date().required(),
    name: yup.string().required(),
    website: yup
      .string()
      .url()
      .required(),
    address: yup.string().required()
  }),
  mapPropsToValues: props => ({
    public: 'false',
    hack_club_associated: 'false',
    mlh_associated: 'false',
    collegiate: 'false',
    ...props.event
  }),
  enableReinitialize: true,
  handleSubmit: (values, { props }) => {
    const apiFunction = values.id ? api.patch : api.post
    const apiEndpoint = values.id ? `v1/events/${values.id}` : `v1/events`
    const filteredEvents = {}
    Object.keys(values).forEach(key => {
      if (['banner', 'logo'].indexOf(key) !== -1 && values[key]) {
        filteredEvents[`${key}_id`] = values[key].id
      } else if (key === 'hack_club_associated') {
        filteredEvents[key] = values[key] === 'true'
      } else {
        filteredEvents[key] = values[key]
      }
    })
    apiFunction(apiEndpoint, { data: filteredEvents }).then(event => {
      props.updateEvent(event)
    })
  }
})(InnerForm)
<commit_msg>Revert "Add admin fields for mlh & collegiate hackathons"<commit_after>import React, { Fragment } from 'react'
import { withFormik } from 'formik'
import yup from 'yup'
import api from 'api'
import { AutoSaver, Field, Submit } from 'components/Forms'
import { Button, Text, Label } from '@hackclub/design-system'

const InnerForm = ({
  values,
  errors,
  touched,
  handleChange,
  handleBlur,
  handleSubmit,
  isSubmitting
}) => (
  <form onSubmit={handleSubmit}>
    <Field
      label={
        <Fragment>
          Should this event be listed on{' '}

            hackathons.hackclub.com
          ?
        </Fragment>
      }
      name="public"
      value={values.public}
      error={touched.public && errors.public}
      onChange={handleChange}
      onBlur={handleBlur}
      type="select"
    >
      <option value="false">No</option>
      <option value="true">Yes</option>
    </Field>
    <Field
      label="Affiliated with Hack Club"
      name="hack_club_associated"
      value={values.hack_club_associated}
      error={touched.hack_club_associated && errors.hack_club_associated}
      onChange={handleChange}
      onBlur={handleBlur}
      type="select"
    >
      <option value="false">No</option>
      <option value="true">Yes</option>
    </Field>
    <Field
      label="How is it associated"
      name="hack_club_associated_notes"
      value={values.hack_club_associated_notes || ''}
      error={
        touched.hack_club_associated_notes && errors.hack_club_associated_notes
      }
      onChange={handleChange}
      onBlur={handleBlur}
    />
    <Field
      label="Start date"
      name="start"
      value={values.start || ''}
      error={touched.start && errors.start}
      onChange={handleChange}
      onBlur={handleBlur}
      type="date"
    />
    <Field
      label="End date"
      name="end"
      value={values.end || ''}
      error={touched.end && errors.end}
      onChange={handleChange}
      onBlur={handleBlur}
      type="date"
    />
    <Field
      label="Event Name"
      name="name"
      value={values.name || ''}
      error={touched.name && errors.name}
      onChange={handleChange}
      onBlur={handleBlur}
    />
    <Field
      label="Event Website"
      name="website"
      value={values.website || ''}
      error={touched.website && errors.website}
      onChange={handleChange}
      onBlur={handleBlur}
      placeholder="https://"
    />
    <Field
      label="Total attendance"
      name="total_attendance"
      value={values.total_attendance || ''}
      error={touched.total_attendance && errors.total_attendance}
      onChange={handleChange}
      onBlur={handleBlur}
      type="number"
    />
    <Field
      label="First time hackathon estimate"
      name="first_time_hackathon_estimate"
      value={values.first_time_hackathon_estimate || ''}
      error={
        touched.first_time_hackathon_estimate &&
        errors.first_time_hackathon_estimate
      }
      onChange={handleChange}
      onBlur={handleBlur}
      type="number"
    />
    <Field
      label="Address"
      name="address"
      value={values.address || ''}
      error={touched.address && errors.address}
      onChange={handleChange}
      onBlur={handleBlur}
      type="textarea"
    />
    <Button onClick={handleSubmit}>
      {isSubmitting ? 'Submitting...' : values.id ? 'Update' : 'Create'}
    </Button>
  </form>
)

export default withFormik({
  validationSchema: yup.object().shape({
    public: yup.string().required(),
    hack_club_associated: yup.string().required(),
    hack_club_associated_notes: yup.string().nullable(),
    start: yup.date().required(),
    end: yup.date().required(),
    name: yup.string().required(),
    website: yup
      .string()
      .url()
      .required(),
    address: yup.string().required()
  }),
  mapPropsToValues: props => ({
    public: 'false',
    hack_club_associated: 'false',
    mlh_associated: 'false',
    collegiate: 'false',
    ...props.event
  }),
  enableReinitialize: true,
  handleSubmit: (values, { props }) => {
    const apiFunction = values.id ? api.patch : api.post
    const apiEndpoint = values.id ? `v1/events/${values.id}` : `v1/events`
    const filteredEvents = {}
    Object.keys(values).forEach(key => {
      if (['banner', 'logo'].indexOf(key) !== -1 && values[key]) {
        filteredEvents[`${key}_id`] = values[key].id
      } else if (key === 'hack_club_associated') {
        filteredEvents[key] = values[key] === 'true'
      } else {
        filteredEvents[key] = values[key]
      }
    })
    apiFunction(apiEndpoint, { data: filteredEvents }).then(event => {
      props.updateEvent(event)
    })
  }
})(InnerForm)
<|endoftext|>


<commit_before>"use strict";

module.exports = {
  "parser": "babel-eslint",
  "plugins": [
    "react"
  ],
  "ecmaFeatures": {
    "jsx": false
  },
  "rules": {
    // Prevent missing displayName in a React component definition
    "react/display-name": 0,
    // Forbid certain propTypes
    "react/forbid-prop-types": 0,
    // Enforce boolean attributes notation in JSX
    "react/jsx-boolean-value": 2,
    // Validate closing bracket location in JSX
    "react/jsx-closing-bracket-location": 0,
    // Enforce or disallow spaces inside of curly braces in JSX attributes
    "react/jsx-curly-spacing": 0,
    // Validate props indentation in JSX
    "react/jsx-indent-props": 0,
    // Limit maximum of props on a single line in JSX
    "react/jsx-max-props-per-line": 0,
    // Prevent duplicate props in JSX
    "react/jsx-no-duplicate-props": 0,
    // Prevent usage of unwrapped JSX strings
    "react/jsx-no-literals": 0,
    // Disallow undeclared variables in JSX
    "react/jsx-no-undef": 2,
    // Enforce quote style for JSX attributes
    "react/jsx-quotes": 2,
    // Enforce propTypes declarations alphabetical sorting
    "react/jsx-sort-prop-types": 0,
    // Enforce props alphabetical sorting
    "react/jsx-sort-props": 0,
    // Prevent React to be incorrectly marked as unused
    "react/jsx-uses-react": 2,
    // Prevent variables used in JSX to be incorrectly marked as unused
    "react/jsx-uses-vars": 2,
    // Prevent usage of dangerous JSX properties
    "react/no-danger": 0,
    // Prevent usage of setState in componentDidMount
    "react/no-did-mount-set-state": 2,
    // Prevent usage of setState in componentDidUpdate
    "react/no-did-update-set-state": 2,
    // Prevent direct mutation of this.state
    "react/no-direct-mutation-state": 0,
    // Prevent multiple component definition per file
    "react/no-multi-comp": 0,
    // Prevent usage of setState
    "react/no-set-state": 0,
    // Prevent usage of unknown DOM property
    "react/no-unknown-property": 2,
    // Prevent missing props validation in a React component definition
    "react/prop-types": 2,
    // Prevent missing React when using JSX
    "react/react-in-jsx-scope": 2,
    // Restrict file extensions that may be required
    "react/require-extension": 0,
    // Prevent extra closing tags for components without children
    "react/self-closing-comp": 2,
    // Enforce component methods order
    "react/sort-comp": 0,
    // Prevent missing parentheses around multilines JSX
    "react/wrap-multilines": 2
  }
};
<commit_msg>Add Walmart specific defaults<commit_after>"use strict";

module.exports = {
  "parser": "babel-eslint",
  "plugins": [
    "react"
  ],
  "ecmaFeatures": {
    "jsx": false
  },
  "rules": {
    // Prevent missing displayName in a React component definition
    "react/display-name": 0,
    // Forbid certain propTypes
    "react/forbid-prop-types": 0,
    // Enforce boolean attributes notation in JSX
    "react/jsx-boolean-value": 2,
    // Validate closing bracket location in JSX
    "react/jsx-closing-bracket-location": [2, 'tag-aligned'],
    // Enforce or disallow spaces inside of curly braces in JSX attributes
    "react/jsx-curly-spacing": 0,
    // Validate props indentation in JSX
    "react/jsx-indent-props": [2, 2],
    // Limit maximum of props on a single line in JSX
    "react/jsx-max-props-per-line": 0,
    // Prevent duplicate props in JSX
    "react/jsx-no-duplicate-props": 0,
    // Prevent usage of unwrapped JSX strings
    "react/jsx-no-literals": 0,
    // Disallow undeclared variables in JSX
    "react/jsx-no-undef": 2,
    // Enforce quote style for JSX attributes
    "react/jsx-quotes": 2,
    // Enforce propTypes declarations alphabetical sorting
    "react/jsx-sort-prop-types": 0,
    // Enforce props alphabetical sorting
    "react/jsx-sort-props": 0,
    // Prevent React to be incorrectly marked as unused
    "react/jsx-uses-react": 2,
    // Prevent variables used in JSX to be incorrectly marked as unused
    "react/jsx-uses-vars": 2,
    // Prevent usage of dangerous JSX properties
    "react/no-danger": 0,
    // Prevent usage of setState in componentDidMount
    "react/no-did-mount-set-state": 2,
    // Prevent usage of setState in componentDidUpdate
    "react/no-did-update-set-state": 2,
    // Prevent direct mutation of this.state
    "react/no-direct-mutation-state": 2,
    // Prevent multiple component definition per file
    "react/no-multi-comp": 0,
    // Prevent usage of setState
    "react/no-set-state": 0,
    // Prevent usage of unknown DOM property
    "react/no-unknown-property": 2,
    // Prevent missing props validation in a React component definition
    "react/prop-types": 2,
    // Prevent missing React when using JSX
    "react/react-in-jsx-scope": 2,
    // Restrict file extensions that may be required
    "react/require-extension": 0,
    // Prevent extra closing tags for components without children
    "react/self-closing-comp": 2,
    // Enforce component methods order
    "react/sort-comp": 0,
    // Prevent missing parentheses around multilines JSX
    "react/wrap-multilines": 2
  }
};
<|endoftext|>


<commit_before>/**
 * handlebars helper: {{component ComponentName Data Variation}}
 *
 * Usage
 * {{component 'Button' 'button-fancy'}}
 * {{component name='Button' data='button-fancy'}}
 *
 * Usage (passing arguments)
 * {{component name='Button' disabled=true}}
 *
 * Usage (with children)
 * {{#component name='Button'}}Click Me{{/component}}
 * {{#component name='Button' disabled=true}}Not Clickable{{/component}}
 *
 */
var fs = require('fs');
var hbs = require('hbs');
var path = require('path');
var extend = require('extend');
var cfg = require('../core/config');
var utils = require('../core/utils');

module.exports = function component () {

	try {
		var context = arguments[arguments.length - 1];
		var contextDataRoot = context.data && context.data.root ? context.data.root : {};      // default component data from controller & view
		var name = 'string' === typeof arguments[0] ? arguments[0] : context.hash.name;
		var folder = name.replace(/[^A-Za-z0-9-]/g, '');
		var templateFile = context.hash && context.hash.template ? context.hash.template : folder.toLowerCase();
		var dataFile = folder.toLowerCase();                                                   // default data file
		var passedData = null;                                                                 // passed data to component helper
		var componentData = {};                                                                // collected component data

		if (arguments.length >= 3) {
			if ('object' === typeof arguments[1]) {
				passedData = arguments[1];
			}
			else if('string' === typeof arguments[1]) {
				dataFile = arguments[1].replace(/\.json$/i, '').toLowerCase();
			}
		}
		else if (context.hash && context.hash.data) {
			if ('object' === typeof context.hash.data) {
				passedData = context.hash.data;
			}
			else if ('string' === typeof context.hash.data) {
				dataFile = context.hash.data;
			}
		}

		for (var key in cfg.nitro.components) {
			if (cfg.nitro.components.hasOwnProperty(key)) {
				var component = cfg.nitro.components[key];
				if (component.hasOwnProperty('path')) {
					var templatePath = path.join(
						cfg.nitro.base_path,
						component.path,
						'/',
						folder,
						'/',
						templateFile + '.' + cfg.nitro.view_file_extension
					);

					if (utils.fileExistsSync(templatePath)) {
						var jsonFilename = dataFile + '.json',
							jsonPath = path.join(
								cfg.nitro.base_path,
								component.path,
								'/',
								folder,
								'/_data/',
								jsonFilename
							);

						try {
							if (contextDataRoot._locals) {
								extend(true, componentData, contextDataRoot._locals);
							}

							if (passedData) {
								extend(true, componentData, passedData);
							}
							else if (utils.fileExistsSync(jsonPath)) {
								extend(true, componentData, JSON.parse(fs.readFileSync(jsonPath, 'utf8')));
							}

							if (contextDataRoot._query) {
								extend(true, componentData, contextDataRoot._query);
							}

							// Add attribtues e.g. "disabled" of {{component "Button" disabled=true}}
							if (context.hash) {
								extend(true, componentData, context.hash);
							}

							// Add children e.g. {{#component "Button"}}Click me{{/component}}
							if (context.fn) {
								componentData.children = context.fn(this);
							}

							return new hbs.handlebars.SafeString(
								hbs.handlebars.compile(
									fs.readFileSync(templatePath, 'utf8')
								)(componentData, context)
							);
						}
						catch (e) {
							throw new Error('Parse Error in Component ' + name + ': ' + e.message);
						}
					}
				}
			}
		}

		throw new Error('Component `' + name + '` with template file `'+ templateFile + '.' + cfg.nitro.view_file_extension + '` not found in folder `' + folder + '`.');
	}
	catch (e) {
		return utils.logAndRenderError(e);
	}
};
<commit_msg>Fixes data file case sensitivity problem<commit_after>/**
 * handlebars helper: {{component ComponentName Data Variation}}
 *
 * Usage
 * {{component 'Button' 'button-fancy'}}
 * {{component name='Button' data='button-fancy'}}
 *
 * Usage (passing arguments)
 * {{component name='Button' disabled=true}}
 *
 * Usage (with children)
 * {{#component name='Button'}}Click Me{{/component}}
 * {{#component name='Button' disabled=true}}Not Clickable{{/component}}
 *
 */
var fs = require('fs');
var hbs = require('hbs');
var path = require('path');
var extend = require('extend');
var cfg = require('../core/config');
var utils = require('../core/utils');

module.exports = function component () {

	try {
		var context = arguments[arguments.length - 1];
		var contextDataRoot = context.data && context.data.root ? context.data.root : {};      // default component data from controller & view
		var name = 'string' === typeof arguments[0] ? arguments[0] : context.hash.name;
		var folder = name.replace(/[^A-Za-z0-9-]/g, '');
		var templateFile = context.hash && context.hash.template ? context.hash.template : folder.toLowerCase();
		var dataFile = folder.toLowerCase();                                                   // default data file
		var passedData = null;                                                                 // passed data to component helper
		var componentData = {};                                                                // collected component data

		if (arguments.length >= 3) {
			if ('object' === typeof arguments[1]) {
				passedData = arguments[1];
			}
			else if('string' === typeof arguments[1]) {
				dataFile = arguments[1].replace(/\.json$/i, '').toLowerCase();
			}
		}
		else if (context.hash && context.hash.data) {
			if ('object' === typeof context.hash.data) {
				passedData = context.hash.data;
			}
			else if ('string' === typeof context.hash.data) {
				dataFile = context.hash.data.toLowerCase();
			}
		}

		for (var key in cfg.nitro.components) {
			if (cfg.nitro.components.hasOwnProperty(key)) {
				var component = cfg.nitro.components[key];
				if (component.hasOwnProperty('path')) {
					var templatePath = path.join(
						cfg.nitro.base_path,
						component.path,
						'/',
						folder,
						'/',
						templateFile + '.' + cfg.nitro.view_file_extension
					);

					if (utils.fileExistsSync(templatePath)) {
						var jsonFilename = dataFile + '.json',
							jsonPath = path.join(
								cfg.nitro.base_path,
								component.path,
								'/',
								folder,
								'/_data/',
								jsonFilename
							);

						try {
							if (contextDataRoot._locals) {
								extend(true, componentData, contextDataRoot._locals);
							}

							if (passedData) {
								extend(true, componentData, passedData);
							}
							else if (utils.fileExistsSync(jsonPath)) {
								extend(true, componentData, JSON.parse(fs.readFileSync(jsonPath, 'utf8')));
							}

							if (contextDataRoot._query) {
								extend(true, componentData, contextDataRoot._query);
							}

							// Add attribtues e.g. "disabled" of {{component "Button" disabled=true}}
							if (context.hash) {
								extend(true, componentData, context.hash);
							}

							// Add children e.g. {{#component "Button"}}Click me{{/component}}
							if (context.fn) {
								componentData.children = context.fn(this);
							}

							return new hbs.handlebars.SafeString(
								hbs.handlebars.compile(
									fs.readFileSync(templatePath, 'utf8')
								)(componentData, context)
							);
						}
						catch (e) {
							throw new Error('Parse Error in Component ' + name + ': ' + e.message);
						}
					}
				}
			}
		}

		throw new Error('Component `' + name + '` with template file `'+ templateFile + '.' + cfg.nitro.view_file_extension + '` not found in folder `' + folder + '`.');
	}
	catch (e) {
		return utils.logAndRenderError(e);
	}
};
<|endoftext|>


<commit_before>import Utils from '../../../utils/utils';

export default function (event) {
  const swiper = this;
  const data = swiper.touchEventsData;

  const {
    params, touches, rtlTranslate: rtl, $wrapperEl, slidesGrid, snapGrid,
  } = swiper;
  let e = event;
  if (e.originalEvent) e = e.originalEvent;
  if (data.allowTouchCallbacks) {
    swiper.emit('touchEnd', e);
  }
  data.allowTouchCallbacks = false;
  if (!data.isTouched) {
    if (data.isMoved && params.grabCursor) {
      swiper.setGrabCursor(false);
    }
    data.isMoved = false;
    data.startMoving = false;
    return;
  }
  // Return Grab Cursor
  if (params.grabCursor && data.isMoved && data.isTouched && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
    swiper.setGrabCursor(false);
  }

  // Time diff
  const touchEndTime = Utils.now();
  const timeDiff = touchEndTime - data.touchStartTime;

  // Tap, doubleTap, Click
  if (swiper.allowClick) {
    swiper.updateClickedSlide(e);
    swiper.emit('tap click', e);
    if (timeDiff < 300 && (touchEndTime - data.lastClickTime) < 300) {
      swiper.emit('doubleTap doubleClick', e);
    }
  }

  data.lastClickTime = Utils.now();
  Utils.nextTick(() => {
    if (!swiper.destroyed) swiper.allowClick = true;
  });

  if (!data.isTouched || !data.isMoved || !swiper.swipeDirection || touches.diff === 0 || data.currentTranslate === data.startTranslate) {
    data.isTouched = false;
    data.isMoved = false;
    data.startMoving = false;
    return;
  }
  data.isTouched = false;
  data.isMoved = false;
  data.startMoving = false;

  let currentPos;
  if (params.followFinger) {
    currentPos = rtl ? swiper.translate : -swiper.translate;
  } else {
    currentPos = -data.currentTranslate;
  }

  if (params.cssMode) {
    return;
  }

  if (params.freeMode) {
    if (currentPos < -swiper.minTranslate()) {
      swiper.slideTo(swiper.activeIndex);
      return;
    }
    if (currentPos > -swiper.maxTranslate()) {
      if (swiper.slides.length < snapGrid.length) {
        swiper.slideTo(snapGrid.length - 1);
      } else {
        swiper.slideTo(swiper.slides.length - 1);
      }
      return;
    }

    if (params.freeModeMomentum) {
      if (data.velocities.length > 1) {
        const lastMoveEvent = data.velocities.pop();
        const velocityEvent = data.velocities.pop();

        const distance = lastMoveEvent.position - velocityEvent.position;
        const time = lastMoveEvent.time - velocityEvent.time;
        swiper.velocity = distance / time;
        swiper.velocity /= 2;
        if (Math.abs(swiper.velocity) < params.freeModeMinimumVelocity) {
          swiper.velocity = 0;
        }
        // this implies that the user stopped moving a finger then released.
        // There would be no events with distance zero, so the last event is stale.
        if (time > 150 || (Utils.now() - lastMoveEvent.time) > 300) {
          swiper.velocity = 0;
        }
      } else {
        swiper.velocity = 0;
      }
      swiper.velocity *= params.freeModeMomentumVelocityRatio;

      data.velocities.length = 0;
      let momentumDuration = 1000 * params.freeModeMomentumRatio;
      const momentumDistance = swiper.velocity * momentumDuration;

      let newPosition = swiper.translate + momentumDistance;
      if (rtl) newPosition = -newPosition;

      let doBounce = false;
      let afterBouncePosition;
      const bounceAmount = Math.abs(swiper.velocity) * 20 * params.freeModeMomentumBounceRatio;
      let needsLoopFix;
      if (newPosition < swiper.maxTranslate()) {
        if (params.freeModeMomentumBounce) {
          if (newPosition + swiper.maxTranslate() < -bounceAmount) {
            newPosition = swiper.maxTranslate() - bounceAmount;
          }
          afterBouncePosition = swiper.maxTranslate();
          doBounce = true;
          data.allowMomentumBounce = true;
        } else {
          newPosition = swiper.maxTranslate();
        }
        if (params.loop && params.centeredSlides) needsLoopFix = true;
      } else if (newPosition > swiper.minTranslate()) {
        if (params.freeModeMomentumBounce) {
          if (newPosition - swiper.minTranslate() > bounceAmount) {
            newPosition = swiper.minTranslate() + bounceAmount;
          }
          afterBouncePosition = swiper.minTranslate();
          doBounce = true;
          data.allowMomentumBounce = true;
        } else {
          newPosition = swiper.minTranslate();
        }
        if (params.loop && params.centeredSlides) needsLoopFix = true;
      } else if (params.freeModeSticky) {
        let nextSlide;
        for (let j = 0; j < snapGrid.length; j += 1) {
          if (snapGrid[j] > -newPosition) {
            nextSlide = j;
            break;
          }
        }

        if (Math.abs(snapGrid[nextSlide] - newPosition) < Math.abs(snapGrid[nextSlide - 1] - newPosition) || swiper.swipeDirection === 'next') {
          newPosition = snapGrid[nextSlide];
        } else {
          newPosition = snapGrid[nextSlide - 1];
        }
        newPosition = -newPosition;
      }
      if (needsLoopFix) {
        swiper.once('transitionEnd', () => {
          swiper.loopFix();
        });
      }
      // Fix duration
      if (swiper.velocity !== 0) {
        if (rtl) {
          momentumDuration = Math.abs((-newPosition - swiper.translate) / swiper.velocity);
        } else {
          momentumDuration = Math.abs((newPosition - swiper.translate) / swiper.velocity);
        }
        if (params.freeModeSticky) {
          // If freeModeSticky is active and the user ends a swipe with a slow-velocity
          // event, then durations can be 20+ seconds to slide one (or zero!) slides.
          // It's easy to see this when simulating touch with mouse events. To fix this,
          // limit single-slide swipes to the default slide duration. This also has the
          // nice side effect of matching slide speed if the user stopped moving before
          // lifting finger or mouse vs. moving slowly before lifting the finger/mouse.
          // For faster swipes, also apply limits (albeit higher ones).
          const moveDistance = Math.abs((rtl ? -newPosition : newPosition) - swiper.translate);
          const currentSlideSize = swiper.slidesSizesGrid[swiper.activeIndex];
          if (moveDistance < currentSlideSize) {
            momentumDuration = params.speed;
          } else if (moveDistance < 2 * currentSlideSize) {
            momentumDuration = params.speed * 1.5;
          } else {
            momentumDuration = params.speed * 2.5;
          }
        }
      } else if (params.freeModeSticky) {
        swiper.slideToClosest();
        return;
      }

      if (params.freeModeMomentumBounce && doBounce) {
        swiper.updateProgress(afterBouncePosition);
        swiper.setTransition(momentumDuration);
        swiper.setTranslate(newPosition);
        swiper.transitionStart(true, swiper.swipeDirection);
        swiper.animating = true;
        $wrapperEl.transitionEnd(() => {
          if (!swiper || swiper.destroyed || !data.allowMomentumBounce) return;
          swiper.emit('momentumBounce');

          swiper.setTransition(params.speed);
          swiper.setTranslate(afterBouncePosition);
          $wrapperEl.transitionEnd(() => {
            if (!swiper || swiper.destroyed) return;
            swiper.transitionEnd();
          });
        });
      } else if (swiper.velocity) {
        swiper.updateProgress(newPosition);
        swiper.setTransition(momentumDuration);
        swiper.setTranslate(newPosition);
        swiper.transitionStart(true, swiper.swipeDirection);
        if (!swiper.animating) {
          swiper.animating = true;
          $wrapperEl.transitionEnd(() => {
            if (!swiper || swiper.destroyed) return;
            swiper.transitionEnd();
          });
        }
      } else {
        swiper.updateProgress(newPosition);
      }

      swiper.updateActiveIndex();
      swiper.updateSlidesClasses();
    } else if (params.freeModeSticky) {
      swiper.slideToClosest();
      return;
    }

    if (!params.freeModeMomentum || timeDiff >= params.longSwipesMs) {
      swiper.updateProgress();
      swiper.updateActiveIndex();
      swiper.updateSlidesClasses();
    }
    return;
  }

  // Find current slide
  let stopIndex = 0;
  let groupSize = swiper.slidesSizesGrid[0];
  for (let i = 0; i < slidesGrid.length; i += (i < params.slidesPerGroupSkip ? 1 : params.slidesPerGroup)) {
    const increment = (i < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup);
    if (typeof slidesGrid[i + increment] !== 'undefined') {
      if (currentPos >= slidesGrid[i] && currentPos < slidesGrid[i + increment]) {
        stopIndex = i;
        groupSize = slidesGrid[i + increment] - slidesGrid[i];
      }
    } else if (currentPos >= slidesGrid[i]) {
      stopIndex = i;
      groupSize = slidesGrid[slidesGrid.length - 1] - slidesGrid[slidesGrid.length - 2];
    }
  }

  // Find current slide size
  const ratio = (currentPos - slidesGrid[stopIndex]) / groupSize;
  const increment = (stopIndex < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup);

  if (timeDiff > params.longSwipesMs) {
    // Long touches
    if (!params.longSwipes) {
      swiper.slideTo(swiper.activeIndex);
      return;
    }
    if (swiper.swipeDirection === 'next') {
      if (ratio >= params.longSwipesRatio) swiper.slideTo(stopIndex + increment);
      else swiper.slideTo(stopIndex);
    }
    if (swiper.swipeDirection === 'prev') {
      if (ratio > (1 - params.longSwipesRatio)) swiper.slideTo(stopIndex + increment);
      else swiper.slideTo(stopIndex);
    }
  } else {
    // Short swipes
    if (!params.shortSwipes) {
      swiper.slideTo(swiper.activeIndex);
      return;
    }
    const isNavButtonTarget = swiper.navigation && (e.target === swiper.navigation.nextEl || e.target === swiper.navigation.prevEl);
    if (!isNavButtonTarget) {
      if (swiper.swipeDirection === 'next') {
        swiper.slideTo(stopIndex + increment);
      }
      if (swiper.swipeDirection === 'prev') {
        swiper.slideTo(stopIndex);
      }
    } else if (e.target === swiper.navigation.nextEl) {
      swiper.slideTo(stopIndex + increment);
    } else {
      swiper.slideTo(stopIndex);
    }
  }
}
<commit_msg>Core: Fix momenum bounce bug on iOS<commit_after>import Utils from '../../../utils/utils';

export default function (event) {
  const swiper = this;
  const data = swiper.touchEventsData;

  const {
    params, touches, rtlTranslate: rtl, $wrapperEl, slidesGrid, snapGrid,
  } = swiper;
  let e = event;
  if (e.originalEvent) e = e.originalEvent;
  if (data.allowTouchCallbacks) {
    swiper.emit('touchEnd', e);
  }
  data.allowTouchCallbacks = false;
  if (!data.isTouched) {
    if (data.isMoved && params.grabCursor) {
      swiper.setGrabCursor(false);
    }
    data.isMoved = false;
    data.startMoving = false;
    return;
  }
  // Return Grab Cursor
  if (params.grabCursor && data.isMoved && data.isTouched && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
    swiper.setGrabCursor(false);
  }

  // Time diff
  const touchEndTime = Utils.now();
  const timeDiff = touchEndTime - data.touchStartTime;

  // Tap, doubleTap, Click
  if (swiper.allowClick) {
    swiper.updateClickedSlide(e);
    swiper.emit('tap click', e);
    if (timeDiff < 300 && (touchEndTime - data.lastClickTime) < 300) {
      swiper.emit('doubleTap doubleClick', e);
    }
  }

  data.lastClickTime = Utils.now();
  Utils.nextTick(() => {
    if (!swiper.destroyed) swiper.allowClick = true;
  });

  if (!data.isTouched || !data.isMoved || !swiper.swipeDirection || touches.diff === 0 || data.currentTranslate === data.startTranslate) {
    data.isTouched = false;
    data.isMoved = false;
    data.startMoving = false;
    return;
  }
  data.isTouched = false;
  data.isMoved = false;
  data.startMoving = false;

  let currentPos;
  if (params.followFinger) {
    currentPos = rtl ? swiper.translate : -swiper.translate;
  } else {
    currentPos = -data.currentTranslate;
  }

  if (params.cssMode) {
    return;
  }

  if (params.freeMode) {
    if (currentPos < -swiper.minTranslate()) {
      swiper.slideTo(swiper.activeIndex);
      return;
    }
    if (currentPos > -swiper.maxTranslate()) {
      if (swiper.slides.length < snapGrid.length) {
        swiper.slideTo(snapGrid.length - 1);
      } else {
        swiper.slideTo(swiper.slides.length - 1);
      }
      return;
    }

    if (params.freeModeMomentum) {
      if (data.velocities.length > 1) {
        const lastMoveEvent = data.velocities.pop();
        const velocityEvent = data.velocities.pop();

        const distance = lastMoveEvent.position - velocityEvent.position;
        const time = lastMoveEvent.time - velocityEvent.time;
        swiper.velocity = distance / time;
        swiper.velocity /= 2;
        if (Math.abs(swiper.velocity) < params.freeModeMinimumVelocity) {
          swiper.velocity = 0;
        }
        // this implies that the user stopped moving a finger then released.
        // There would be no events with distance zero, so the last event is stale.
        if (time > 150 || (Utils.now() - lastMoveEvent.time) > 300) {
          swiper.velocity = 0;
        }
      } else {
        swiper.velocity = 0;
      }
      swiper.velocity *= params.freeModeMomentumVelocityRatio;

      data.velocities.length = 0;
      let momentumDuration = 1000 * params.freeModeMomentumRatio;
      const momentumDistance = swiper.velocity * momentumDuration;

      let newPosition = swiper.translate + momentumDistance;
      if (rtl) newPosition = -newPosition;

      let doBounce = false;
      let afterBouncePosition;
      const bounceAmount = Math.abs(swiper.velocity) * 20 * params.freeModeMomentumBounceRatio;
      let needsLoopFix;
      if (newPosition < swiper.maxTranslate()) {
        if (params.freeModeMomentumBounce) {
          if (newPosition + swiper.maxTranslate() < -bounceAmount) {
            newPosition = swiper.maxTranslate() - bounceAmount;
          }
          afterBouncePosition = swiper.maxTranslate();
          doBounce = true;
          data.allowMomentumBounce = true;
        } else {
          newPosition = swiper.maxTranslate();
        }
        if (params.loop && params.centeredSlides) needsLoopFix = true;
      } else if (newPosition > swiper.minTranslate()) {
        if (params.freeModeMomentumBounce) {
          if (newPosition - swiper.minTranslate() > bounceAmount) {
            newPosition = swiper.minTranslate() + bounceAmount;
          }
          afterBouncePosition = swiper.minTranslate();
          doBounce = true;
          data.allowMomentumBounce = true;
        } else {
          newPosition = swiper.minTranslate();
        }
        if (params.loop && params.centeredSlides) needsLoopFix = true;
      } else if (params.freeModeSticky) {
        let nextSlide;
        for (let j = 0; j < snapGrid.length; j += 1) {
          if (snapGrid[j] > -newPosition) {
            nextSlide = j;
            break;
          }
        }

        if (Math.abs(snapGrid[nextSlide] - newPosition) < Math.abs(snapGrid[nextSlide - 1] - newPosition) || swiper.swipeDirection === 'next') {
          newPosition = snapGrid[nextSlide];
        } else {
          newPosition = snapGrid[nextSlide - 1];
        }
        newPosition = -newPosition;
      }
      if (needsLoopFix) {
        swiper.once('transitionEnd', () => {
          swiper.loopFix();
        });
      }
      // Fix duration
      if (swiper.velocity !== 0) {
        if (rtl) {
          momentumDuration = Math.abs((-newPosition - swiper.translate) / swiper.velocity);
        } else {
          momentumDuration = Math.abs((newPosition - swiper.translate) / swiper.velocity);
        }
        if (params.freeModeSticky) {
          // If freeModeSticky is active and the user ends a swipe with a slow-velocity
          // event, then durations can be 20+ seconds to slide one (or zero!) slides.
          // It's easy to see this when simulating touch with mouse events. To fix this,
          // limit single-slide swipes to the default slide duration. This also has the
          // nice side effect of matching slide speed if the user stopped moving before
          // lifting finger or mouse vs. moving slowly before lifting the finger/mouse.
          // For faster swipes, also apply limits (albeit higher ones).
          const moveDistance = Math.abs((rtl ? -newPosition : newPosition) - swiper.translate);
          const currentSlideSize = swiper.slidesSizesGrid[swiper.activeIndex];
          if (moveDistance < currentSlideSize) {
            momentumDuration = params.speed;
          } else if (moveDistance < 2 * currentSlideSize) {
            momentumDuration = params.speed * 1.5;
          } else {
            momentumDuration = params.speed * 2.5;
          }
        }
      } else if (params.freeModeSticky) {
        swiper.slideToClosest();
        return;
      }

      if (params.freeModeMomentumBounce && doBounce) {
        swiper.updateProgress(afterBouncePosition);
        swiper.setTransition(momentumDuration);
        swiper.setTranslate(newPosition);
        swiper.transitionStart(true, swiper.swipeDirection);
        swiper.animating = true;
        $wrapperEl.transitionEnd(() => {
          if (!swiper || swiper.destroyed || !data.allowMomentumBounce) return;
          swiper.emit('momentumBounce');
          swiper.setTransition(params.speed);
          setTimeout(() => {
            swiper.setTranslate(afterBouncePosition);
            $wrapperEl.transitionEnd(() => {
              if (!swiper || swiper.destroyed) return;
              swiper.transitionEnd();
            });
          }, 0);
        });
      } else if (swiper.velocity) {
        swiper.updateProgress(newPosition);
        swiper.setTransition(momentumDuration);
        swiper.setTranslate(newPosition);
        swiper.transitionStart(true, swiper.swipeDirection);
        if (!swiper.animating) {
          swiper.animating = true;
          $wrapperEl.transitionEnd(() => {
            if (!swiper || swiper.destroyed) return;
            swiper.transitionEnd();
          });
        }
      } else {
        swiper.updateProgress(newPosition);
      }

      swiper.updateActiveIndex();
      swiper.updateSlidesClasses();
    } else if (params.freeModeSticky) {
      swiper.slideToClosest();
      return;
    }

    if (!params.freeModeMomentum || timeDiff >= params.longSwipesMs) {
      swiper.updateProgress();
      swiper.updateActiveIndex();
      swiper.updateSlidesClasses();
    }
    return;
  }

  // Find current slide
  let stopIndex = 0;
  let groupSize = swiper.slidesSizesGrid[0];
  for (let i = 0; i < slidesGrid.length; i += (i < params.slidesPerGroupSkip ? 1 : params.slidesPerGroup)) {
    const increment = (i < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup);
    if (typeof slidesGrid[i + increment] !== 'undefined') {
      if (currentPos >= slidesGrid[i] && currentPos < slidesGrid[i + increment]) {
        stopIndex = i;
        groupSize = slidesGrid[i + increment] - slidesGrid[i];
      }
    } else if (currentPos >= slidesGrid[i]) {
      stopIndex = i;
      groupSize = slidesGrid[slidesGrid.length - 1] - slidesGrid[slidesGrid.length - 2];
    }
  }

  // Find current slide size
  const ratio = (currentPos - slidesGrid[stopIndex]) / groupSize;
  const increment = (stopIndex < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup);

  if (timeDiff > params.longSwipesMs) {
    // Long touches
    if (!params.longSwipes) {
      swiper.slideTo(swiper.activeIndex);
      return;
    }
    if (swiper.swipeDirection === 'next') {
      if (ratio >= params.longSwipesRatio) swiper.slideTo(stopIndex + increment);
      else swiper.slideTo(stopIndex);
    }
    if (swiper.swipeDirection === 'prev') {
      if (ratio > (1 - params.longSwipesRatio)) swiper.slideTo(stopIndex + increment);
      else swiper.slideTo(stopIndex);
    }
  } else {
    // Short swipes
    if (!params.shortSwipes) {
      swiper.slideTo(swiper.activeIndex);
      return;
    }
    const isNavButtonTarget = swiper.navigation && (e.target === swiper.navigation.nextEl || e.target === swiper.navigation.prevEl);
    if (!isNavButtonTarget) {
      if (swiper.swipeDirection === 'next') {
        swiper.slideTo(stopIndex + increment);
      }
      if (swiper.swipeDirection === 'prev') {
        swiper.slideTo(stopIndex);
      }
    } else if (e.target === swiper.navigation.nextEl) {
      swiper.slideTo(stopIndex + increment);
    } else {
      swiper.slideTo(stopIndex);
    }
  }
}
<|endoftext|>