<commit_before>
        // lib code
var   state = require('../haxe-state')
    , run   = require('../haxe-call')
    , uuid = require('../utils/uuid')
    , code = require('../utils/haxe-code')
    , compiler = require('../parsing/compiler')
        // node built in
    , path  = require('path')
        // dep code
    , xml2js = require('xml2js')
    , fs = require('fs-extra')

var REGEX_TYPE_PATH_AFTER = /^([\.A-Za-z0-9_]+)/;
var REGEX_TYPE_PATH_BEFORE = /([\.A-Za-z0-9_]+)$/;

module.exports = {

    init: function() {

            // Don't try anything without valid hxml data
        if(!state.hxml_cwd) return;
        if(!state.hxml_content && !state.hxml_file) return;

            // Extract info from XML once, one second after the haxe server is supposed to be started
            // A better option could be to have an explicit event to catch when the server is ready
        var time = atom.config.get('haxe.server_activation_start_delay');
        setTimeout(this._extract_info_from_xml_output.bind(this), (time + 1) * 1000.0);
    },

    dispose: function() {
        this.info = null;
        this.hxml_for_info = null;
    },

    jump: function() {

            // Don't try anything without valid hxml data
        if(!state.hxml_cwd) return;
        if(!state.hxml_content && !state.hxml_file) return;

        var editor = atom.workspace.getActiveTextEditor();
        var file_path = editor.getPath();

        if(!file_path) return;

        var buffer_pos = editor.getLastCursor().getBufferPosition().toArray();
        var pretext = editor.getTextInBufferRange( [ [0,0], buffer_pos] );
        var text = editor.getText();
        var index = pretext.length;
        var posttext = text.slice(index);

            // Extract selected word (composed), if any
        REGEX_TYPE_PATH_BEFORE.lastIndex = -1;
        REGEX_TYPE_PATH_AFTER.lastIndex = -1;
        var word = '';
        var m;
        if (m = pretext.match(REGEX_TYPE_PATH_BEFORE)) {
            word = m[1];
        }
        if (m = posttext.match(REGEX_TYPE_PATH_AFTER)) {
            word += m[1];
        }
        word = word.replace(/^\.+/, '').replace(/\.+$/, '');

            // By checking if word is uppercase or not, we can
            // deduct whether it can be a type or not
        var word_is_uppercase_type = false;
        var word_last_dot_index = -1;
        var last_word_element = word;
        if (word.length > 0) {
            word_last_dot_index = word.lastIndexOf('.');
            if (word_last_dot_index == -1) {
                if (word.charAt(0).toUpperCase() == word.charAt(0)) {
                    word_is_uppercase_type = true;
                }
            }
            else {
                last_word_element = word.slice(word_last_dot_index + 1);
                if (last_word_element.charAt(0) != null
                && last_word_element.charAt(0).toUpperCase() == last_word_element.charAt(0)) {
                    word_is_uppercase_type = true;
                }
            }
        }

            // Extract end of expression
        var expr_end = code.parse_end_of_expression(text, index);

        var imports = code.extract_imports(text);

            // First, try to query haxe to get position as this is `the good way` to get our job done.
            // Unfortunately it doesn't work in all cases yet
            // If it fails, we fall back to a combination of compiler XML output and @type/@toplevel information
            // Overall, this rather quick implementation should still work in most common cases
        var find_declaration_from_position = function(word) {

            var display_arg = file_path + '@' + Buffer.byteLength(text.slice(0, index + expr_end.length), 'utf8') + '@position';
            this._run_haxe_display(display_arg).then(function(result) {

                xml2js.parseString(result.err, function(err, json) {

                    if (json != null) {
                            // Position got resolved, let's jump!
                        if (json.list != null && json.list.pos != null && json.list.pos.length > 0) {
                            var parsed_pos = compiler.parse_output(json.list.pos[0], {allow_empty_message: true});
                            if (parsed_pos.length > 0) {
                                parsed_pos = parsed_pos[0];
                                this._open({
                                    file: parsed_pos.file_path,
                                    line: parsed_pos.line,
                                    name: word
                                });
                                return;
                            }
                        }
                    }

                        // Fall back to the XML/@type/@toplevel resolution
                    find_declaration_from_xml(word);

                }.bind(this));

            }.bind(this));

        }.bind(this);

        var find_declaration_from_xml = function(word) {

            this._extract_info_from_xml_output().then(function(info) {

                    // Query haxe to get type
                var display_arg = file_path + '@' + Buffer.byteLength(text.slice(0, index + expr_end.length), 'utf8') + '@type';
                this._run_haxe_display(display_arg).then(function(result) {

                    xml2js.parseString(result.err, function(err, json) {

                        if (json != null) {
                                // Type got resolved, let's jump!
                            if (json.type != null && info[json.type.trim()] != null) {
                                this._open(info[json.type.trim()]);
                                return;
                            }
                        }
                        else {
                                // No? Then use @toplevel to try to resolve identifier
                            var index_for_toplevel = code.index_of_closest_block(text, index);

                            display_arg = file_path + '@' + Buffer.byteLength(text.slice(0, index_for_toplevel), 'utf8') + '@toplevel';
                            this._run_haxe_display(display_arg).then(function(result) {

                                xml2js.parseString(result.err, function(err, json) {

                                    if (json != null) {
                                        var types = this._parse_toplevel_list(json);

                                        if (types[word] != null && info[types[word].type] != null) {
                                            this._open(info[types[word].type]);
                                            return;
                                        }

                                    }

                                        // Try to extract file from raw word directly
                                    if (info[word] != null) {
                                        this._open(info[word]);
                                        return;
                                    }
                                    else {
                                            // Last hope, play with packages

                                            // Does it come from an alias?
                                        if (imports[word] != null && info[imports[word]] != null) {
                                            this._open(info[imports[word]]);
                                            return;
                                        }

                                            // Does it come from an imported package?
                                        for (var key in imports) {
                                            var imported_type = imports[key] + '.' + last_word_element;
                                            if (info[imported_type] != null) {
                                                this._open(info[imported_type]);
                                                return;
                                            }
                                        }

                                            // Is it a type of a parent package?
                                        var package_name = code.extract_package(text);
                                        var resolved_type;
                                        while (package_name.length > 0) {
                                                // Is it a type in the current package
                                            if (info[package_name + '.' + last_word_element] != null) {
                                                this._open(info[package_name + '.' + last_word_element]);
                                                return;
                                            }

                                            if (package_name.lastIndexOf('.') != -1) {
                                                package_name = package_name.slice(0, package_name.lastIndexOf('.'));
                                            } else {
                                                break;
                                            }
                                        }

                                            // Is there any other package having this type?
                                        for (var key in info) {
                                            if (key.slice(key.length - last_word_element.length - 1) == ('.' + last_word_element)) {
                                                this._open(info[key]);
                                                return;
                                            }
                                        }

                                            // If the word is composed of multiple identifiers, try removing one element
                                        if (word.lastIndexOf('.') != -1) {
                                            find_declaration_from_xml(word.slice(0, word.lastIndexOf('.')));
                                        }
                                    }

                                }.bind(this));

                            }.bind(this));
                        }

                    }.bind(this));

                }.bind(this));

            }.bind(this));

        }.bind(this);

            // Start resolution
        find_declaration_from_position(word);
    },

    _open: function(info) {
        var file_path;
        var cwd = state.hxml_cwd;

        if (typeof(info) == 'string') {
                // Just open the file
            file_path = info;
            if (!path.isAbsolute(file_path)) {
                file_path = path.join(cwd, file_path);
            }
            atom.workspace.open(info);
        }
        else {
            file_path = info.file;
            if (!path.isAbsolute(file_path)) {
                file_path = path.join(cwd, file_path);
            }

                // Find identifier in content
            var identifier = info.name;
            if (identifier.lastIndexOf('.') != -1) {
                identifier = identifier.slice(identifier.lastIndexOf('.') + 1);
            }

            var contents = String(fs.readFileSync(file_path));

            if (info.line != null) {
                    // Find the characters in line from identifier
                var lines = contents.slice(0, index).split("\n");
                var target_line = lines[info.line-1];

                var regex = new RegExp('[^A-Za-z0-9_]' + identifier + '[^A-Za-z0-9_]');
                var match;
                if (match = target_line.match(regex)) {
                    var line = info.line - 1;
                    var column = target_line.indexOf(match[0]) + match[0].length - identifier.length - 1;
                        // We found it, let's open at the exact location
                    atom.workspace.open(file_path, {
                        initialLine: line,
                        initialColumn: column

                    }).then(function() {

                            // Select the identifier
                        var editor = atom.workspace.getActiveTextEditor();
                        editor.selectToEndOfWord();

                            // Workaround to ensure the editor will be centered to the identifier
                            // Without it, the identifier is often too much at the bottom of the screen
                        editor.scrollToBottom();
                        editor.scrollToCursorPosition();

                    });
                }
                else {
                    atom.workspace.open(file_path, {
                        initialLine: info.line - 1
                    });
                }
            }
            else {
                var cleaned_contents = code.code_with_empty_comments_and_strings(contents);
                var keyword = info.kind;
                if (keyword === 'class') {
                    keyword = '(?:class|interface)';
                }
                var regex = new RegExp(keyword + '\\s+' + identifier + '[^A-Za-z0-9_]');
                var match;
                if (match = cleaned_contents.match(regex)) {
                    var index = cleaned_contents.indexOf(match[0]);
                    var lines = contents.slice(0, index).split("\n");
                    var line = lines.length - 1;
                    var column = lines[lines.length - 1].length + match[0].length - identifier.length - 1;

                        // We found it, let's open at the exact location
                    atom.workspace.open(file_path, {
                        initialLine: line,
                        initialColumn: column

                    }).then(function() {

                            // Select the identifier
                        var editor = atom.workspace.getActiveTextEditor();
                        editor.selectToEndOfWord();

                            // Workaround to ensure the editor will be centered to the identifier
                            // Without it, the identifier is often too much at the bottom of the screen
                        editor.scrollToBottom();
                        editor.scrollToCursorPosition();

                    }.bind(this));

                }
                else {
                    atom.workspace.open(file_path);
                }
            }

        }
    },

    _extract_info_from_xml_output: function() {
        return new Promise(function(resolve, reject) {

                // If info is already extracted, just return it
            if (this.info != null) {
                    // Reset info if hxml is different than previous run
                if (this.hxml_for_info != state.hxml_content) {
                    this.info = null;
                } else {
                    return resolve(this.info);
                }
            }

            var port = atom.config.get('haxe.server_port');
            var tmp_path = state.tmp_path;
            var hash = uuid.v1();
            var xml_path = path.join(tmp_path, hash, 'info.xml');

            fs.ensureDirSync(path.dirname(xml_path));

            var args = [];
            args.push('--no-output');

            if (port) {
                args.push('--connect');
                args.push(String(port));
            }

            args.push('-xml');
            args.push(xml_path);

            args = state.as_args(args);

            run.haxe(args).then((function(result) {

                    // Get xml contents
                var content = fs.readFileSync(xml_path);
                    // Remove file
                fs.removeSync(path.dirname(xml_path));

                xml2js.parseString(content, function (err, json) {

                    if (json == null) return resolve({});

                        // Parse xml result
                    var info = {};
                    var kinds = ['abstract', 'class', 'enum', 'typedef'];
                    for (var i = 0; i < kinds.length; i++) {
                        var kind = kinds[i];
                        var kind_entries = json.haxe[kind];
                        for (var j = 0; j < kind_entries.length; j++) {
                            var entry = kind_entries[j];
                            info[entry.$.path] = {
                                kind: kind,
                                file: entry.$.file,
                                module: entry.$.module,
                                name: entry.$.path
                            };
                        }
                    }

                    var has_keys = false;
                    for (var key in info) {
                        has_keys = true;
                        break;
                    }

                    if (has_keys) {
                        this.hxml_for_info = state.hxml_content;
                        this.info = info;
                        resolve(this.info);
                    } else {
                        resolve({});
                    }

                }.bind(this));

            }).bind(this));

        }.bind(this));
    },

    _parse_toplevel_list: function(json) {

        var types = {};

            // If json is not valid, return empty list
        if (json.il == null || json.il.i == null) return types;

        for (var i = 0; i < json.il.i.length; i++) {
            var raw_entry = json.il.i[i];
            var name = raw_entry._;
            if (types[name] == null) {
                types[name] = {
                    type:   (raw_entry.$.t || raw_entry.$.p),
                    kind:   raw_entry.$.k
                };
            }
        }

        return types;
    },

        // Query haxe server to display information (type, toplevel, position)
    _run_haxe_display: function(display_arg) {

        var port = atom.config.get('haxe.server_port');
        var args = [];
        args.push('--no-output');

        if (port) {
            args.push('--connect');
            args.push(String(port));
        }

        args.push('--display');
        args.push(display_arg);

        args = state.as_args(args);

        return run.haxe(args);
    }

}
<commit_msg>go to declaration; Improve local declaration resolution.<commit_after>
        // lib code
var   state = require('../haxe-state')
    , run   = require('../haxe-call')
    , uuid = require('../utils/uuid')
    , code = require('../utils/haxe-code')
    , compiler = require('../parsing/compiler')
        // node built in
    , path  = require('path')
        // dep code
    , xml2js = require('xml2js')
    , fs = require('fs-extra')

var REGEX_TYPE_PATH_AFTER = /^([\.A-Za-z0-9_]+)/;
var REGEX_TYPE_PATH_BEFORE = /([\.A-Za-z0-9_]+)$/;
var REGEX_IS_IDENTIFIER = /^([A-Za-z_][\.A-Za-z0-9_]+)$/;

module.exports = {

    init: function() {

            // Don't try anything without valid hxml data
        if(!state.hxml_cwd) return;
        if(!state.hxml_content && !state.hxml_file) return;

            // Extract info from XML once, one second after the haxe server is supposed to be started
            // A better option could be to have an explicit event to catch when the server is ready
        var time = atom.config.get('haxe.server_activation_start_delay');
        setTimeout(this._extract_info_from_xml_output.bind(this), (time + 1) * 1000.0);
    },

    dispose: function() {
        this.info = null;
        this.hxml_for_info = null;
    },

    jump: function() {

            // Don't try anything without valid hxml data
        if(!state.hxml_cwd) return;
        if(!state.hxml_content && !state.hxml_file) return;

        var editor = atom.workspace.getActiveTextEditor();
        var file_path = editor.getPath();

        if(!file_path) return;

        var buffer_pos = editor.getLastCursor().getBufferPosition().toArray();
        var pretext = editor.getTextInBufferRange( [ [0,0], buffer_pos] );
        var text = editor.getText();
        var index = pretext.length;
        var posttext = text.slice(index);
        var info = {};

            // Extract selected word (composed), if any
        REGEX_TYPE_PATH_BEFORE.lastIndex = -1;
        REGEX_TYPE_PATH_AFTER.lastIndex = -1;
        var word = '';
        var m;
        if (m = pretext.match(REGEX_TYPE_PATH_BEFORE)) {
            word = m[1];
        }
        if (m = posttext.match(REGEX_TYPE_PATH_AFTER)) {
            word += m[1];
        }
        word = word.replace(/^\.+/, '').replace(/\.+$/, '');

            // By checking if word is uppercase or not, we can
            // deduct whether it can be a type or not
        var word_is_uppercase_type = false;
        var word_last_dot_index = -1;
        var last_word_element = word;
        if (word.length > 0) {
            word_last_dot_index = word.lastIndexOf('.');
            if (word_last_dot_index == -1) {
                if (word.charAt(0).toUpperCase() == word.charAt(0)) {
                    word_is_uppercase_type = true;
                }
            }
            else {
                last_word_element = word.slice(word_last_dot_index + 1);
                if (last_word_element.charAt(0) != null
                && last_word_element.charAt(0).toUpperCase() == last_word_element.charAt(0)) {
                    word_is_uppercase_type = true;
                }
            }
        }

            // Extract end of expression
        var expr_end = code.parse_end_of_expression(text, index);

        var imports = code.extract_imports(text);

            // First, try to query haxe to get position as this is `the good way` to get our job done.
            // Unfortunately it doesn't work in all cases yet
            // If it fails, we fall back to a combination of compiler XML output and @type/@toplevel information
            // Overall, this rather quick implementation should still work in most common cases
        var find_declaration_from_position = function(word) {

            var display_arg = file_path + '@' + Buffer.byteLength(text.slice(0, index + expr_end.length), 'utf8') + '@position';
            this._run_haxe_display(display_arg).then(function(result) {

                xml2js.parseString(result.err, function(err, json) {

                    if (json != null) {
                            // Position got resolved, let's jump!
                        if (json.list != null && json.list.pos != null && json.list.pos.length > 0) {
                            var parsed_pos = compiler.parse_output(json.list.pos[0], {allow_empty_message: true});
                            if (parsed_pos.length > 0) {
                                parsed_pos = parsed_pos[0];
                                this._open({
                                    file: parsed_pos.file_path,
                                    line: parsed_pos.line,
                                    name: word
                                });
                                return;
                            }
                        }
                    }

                        // Fall back to the XML/@type/@toplevel resolution
                    find_declaration_from_xml(word);

                }.bind(this));

            }.bind(this));

        }.bind(this);

        var find_declaration_from_type = function(word) {
                // Query haxe to get type
            var display_arg = file_path + '@' + Buffer.byteLength(text.slice(0, index + expr_end.length), 'utf8') + '@type';
            this._run_haxe_display(display_arg).then(function(result) {

                xml2js.parseString(result.err, function(err, json) {

                    if (json != null) {
                        console.log(json);
                            // Type got resolved, let's jump!
                        if (json.type != null && info[json.type.trim()] != null) {
                            this._open(info[json.type.trim()]);
                            return;
                        }
                    }
                    else {
                        find_declaration_from_toplevel(word);
                    }

                }.bind(this));

            }.bind(this));

        }.bind(this);

        var find_declaration_from_toplevel = function(word) {

                // No? Then use @toplevel to try to resolve identifier
            var index_for_toplevel = code.index_of_closest_block(text, index);

            display_arg = file_path + '@' + Buffer.byteLength(text.slice(0, index_for_toplevel), 'utf8') + '@toplevel';
            this._run_haxe_display(display_arg).then(function(result) {

                xml2js.parseString(result.err, function(err, json) {

                    if (json != null) {
                        var types = this._parse_toplevel_list(json);

                        if (types[word] != null) {
                                // Is this identifier a local declaration?
                            if (types[word] != null && types[word].kind === 'local') {
                                this._open({
                                    file: file_path,
                                    name: word,
                                    local_index: index
                                });
                                return;
                            }

                            if (info[types[word].type] != null) {
                                this._open(info[types[word].type]);
                                return;
                            }
                        }

                    }

                    find_declaration_from_raw_word(word);

                }.bind(this));

            }.bind(this));

        }.bind(this);

        var find_declaration_from_raw_word = function(word) {

                // Try to extract file from raw word directly
            if (info[word] != null) {
                this._open(info[word]);
                return;
            }
            else {
                    // Last hope, play with packages

                    // Does it come from an alias?
                if (imports[word] != null && info[imports[word]] != null) {
                    this._open(info[imports[word]]);
                    return;
                }

                    // Does it come from an imported package?
                for (var key in imports) {
                    var imported_type = imports[key] + '.' + last_word_element;
                    if (info[imported_type] != null) {
                        this._open(info[imported_type]);
                        return;
                    }
                }

                    // Is it a type of a parent package?
                var package_name = code.extract_package(text);
                var resolved_type;
                while (package_name.length > 0) {
                        // Is it a type in the current package
                    if (info[package_name + '.' + last_word_element] != null) {
                        this._open(info[package_name + '.' + last_word_element]);
                        return;
                    }

                    if (package_name.lastIndexOf('.') != -1) {
                        package_name = package_name.slice(0, package_name.lastIndexOf('.'));
                    } else {
                        break;
                    }
                }

                    // Is there any other package having this type?
                for (var key in info) {
                    if (key.slice(key.length - last_word_element.length - 1) == ('.' + last_word_element)) {
                        this._open(info[key]);
                        return;
                    }
                }

                    // If the word is composed of multiple identifiers, try removing one element
                if (word.lastIndexOf('.') != -1) {
                    find_declaration_from_xml(word.slice(0, word.lastIndexOf('.')));
                }
            }

        }.bind(this);

        var find_declaration_from_xml = function(word) {

            this._extract_info_from_xml_output().then(function(parsed_xml_info) {

                info = parsed_xml_info;

                REGEX_IS_IDENTIFIER.lastIndex = -1;
                if (REGEX_IS_IDENTIFIER.test(word)) {
                        // Don't try to extract type from the current word
                    find_declaration_from_toplevel(word);
                }
                else {
                        // The current word is not an identifier. Try to resolve to its type
                    find_declaration_from_type(word);
                }

            }.bind(this));

        }.bind(this);

            // Start resolution
        find_declaration_from_position(word);
    },

    _open: function(info) {
        var file_path;
        var cwd = state.hxml_cwd;

        if (typeof(info) == 'string') {
                // Just open the file
            file_path = info;
            if (!path.isAbsolute(file_path)) {
                file_path = path.join(cwd, file_path);
            }
            atom.workspace.open(info);
        }
        else {
            file_path = info.file;
            if (!path.isAbsolute(file_path)) {
                file_path = path.join(cwd, file_path);
            }

                // Find identifier in content
            var identifier = info.name;
            if (identifier.lastIndexOf('.') != -1) {
                identifier = identifier.slice(identifier.lastIndexOf('.') + 1);
            }

            var contents = String(fs.readFileSync(file_path));

                // Resolve local identifier
            if (info.line == null && info.local_index != null) {
                var cleaned_contents = code.code_with_empty_comments_and_strings(contents).slice(0, info.local_index);

                var regex = new RegExp('(var|\\?|,|\\(|function)\\s*' + identifier + '[^A-Za-z0-9_]', 'g');
                var matches = [];
                cleaned_contents.replace(regex, function() {
                    var match = ([]).slice.call(arguments, 0);
                    matches.push(match);
                });

                for (var i = matches.length - 1; i >= 0; i--) {
                    var prefix = matches[i][1];
                    var index = matches[i][2] + 1;

                    var lines = contents.slice(0, index).split("\n");
                    var line = lines.length - 1;
                        // Jump to variable/function declaration
                    if (prefix === 'var' || prefix === 'function') {
                        var column = lines[lines.length - 1].length + matches[i][0].length - identifier.length - 2;
                        this._update_editor(file_path, line, column);
                    }
                    else {
                        var signature_info = code.parse_partial_signature(contents, index, {parse_declaration: true});
                        if (signature_info != null) {
                                // Jump to function argument
                            var column = lines[lines.length - 1].length + matches[i][0].length - identifier.length - 2;
                            this._update_editor(file_path, line, column);
                        }
                    }
                }
            }
            else if (info.line != null) {
                    // Find the characters in line from identifier
                var lines = contents.slice(0, index).split("\n");
                var target_line = lines[info.line-1];

                var regex = new RegExp('[^A-Za-z0-9_]' + identifier + '[^A-Za-z0-9_]');
                var match;
                if (match = target_line.match(regex)) {
                    var line = info.line - 1;
                    var column = target_line.indexOf(match[0]) + match[0].length - identifier.length - 1;
                        // We found it, let's open at the exact location
                    this._update_editor(file_path, line, column);
                }
                else {
                    this._update_editor(file_path, info.line - 1);
                }
            }
            else {
                var cleaned_contents = code.code_with_empty_comments_and_strings(contents);
                var keyword = info.kind;
                if (keyword === 'class') {
                    keyword = '(?:class|interface)';
                }
                var regex = new RegExp(keyword + '\\s+' + identifier + '[^A-Za-z0-9_]');
                var match;
                if (match = cleaned_contents.match(regex)) {
                    var index = cleaned_contents.indexOf(match[0]);
                    var lines = contents.slice(0, index).split("\n");
                    var line = lines.length - 1;
                    var column = lines[lines.length - 1].length + match[0].length - identifier.length - 1;

                        // We found it, let's open at the exact location
                    this._update_editor(file_path, line, column);
                }
                else {
                    this._update_editor(file_path);
                }
            }

        }
    },

    _update_editor: function(file_path, line, column) {

        var params = {};
        if (line != null) params.initialLine = line;
        if (column != null) params.initialColumn = column;

        atom.workspace.open(file_path, params).then(function() {

            if (column != null) {
                    // Select the identifier
                var editor = atom.workspace.getActiveTextEditor();
                editor.selectToEndOfWord();

                    // Workaround to ensure the editor will be centered to the identifier
                    // Without it, the identifier is often too much at the bottom of the screen
                editor.scrollToBottom();
                editor.scrollToCursorPosition();
            }

        }.bind(this));
    },

    _extract_info_from_xml_output: function() {
        return new Promise(function(resolve, reject) {

                // If info is already extracted, just return it
            if (this.info != null) {
                    // Reset info if hxml is different than previous run
                if (this.hxml_for_info != state.hxml_content) {
                    this.info = null;
                } else {
                    return resolve(this.info);
                }
            }

            var port = atom.config.get('haxe.server_port');
            var tmp_path = state.tmp_path;
            var hash = uuid.v1();
            var xml_path = path.join(tmp_path, hash, 'info.xml');

            fs.ensureDirSync(path.dirname(xml_path));

            var args = [];
            args.push('--no-output');

            if (port) {
                args.push('--connect');
                args.push(String(port));
            }

            args.push('-xml');
            args.push(xml_path);

            args = state.as_args(args);

            run.haxe(args).then((function(result) {

                    // Get xml contents
                var content = fs.readFileSync(xml_path);
                    // Remove file
                fs.removeSync(path.dirname(xml_path));

                xml2js.parseString(content, function (err, json) {

                    if (json == null) return resolve({});

                        // Parse xml result
                    var info = {};
                    var kinds = ['abstract', 'class', 'enum', 'typedef'];
                    for (var i = 0; i < kinds.length; i++) {
                        var kind = kinds[i];
                        var kind_entries = json.haxe[kind];
                        for (var j = 0; j < kind_entries.length; j++) {
                            var entry = kind_entries[j];
                            info[entry.$.path] = {
                                kind: kind,
                                file: entry.$.file,
                                module: entry.$.module,
                                name: entry.$.path
                            };
                        }
                    }

                    var has_keys = false;
                    for (var key in info) {
                        has_keys = true;
                        break;
                    }

                    if (has_keys) {
                        this.hxml_for_info = state.hxml_content;
                        this.info = info;
                        resolve(this.info);
                    } else {
                        resolve({});
                    }

                }.bind(this));

            }).bind(this));

        }.bind(this));
    },

    _parse_toplevel_list: function(json) {

        var types = {};

            // If json is not valid, return empty list
        if (json.il == null || json.il.i == null) return types;

        for (var i = 0; i < json.il.i.length; i++) {
            var raw_entry = json.il.i[i];
            var name = raw_entry._;
            if (types[name] == null) {
                types[name] = {
                    type:   (String(raw_entry.$.t || raw_entry.$.p).trim()),
                    kind:   raw_entry.$.k
                };
            }
        }

        return types;
    },

        // Query haxe server to display information (type, toplevel, position)
    _run_haxe_display: function(display_arg) {

        var port = atom.config.get('haxe.server_port');
        var args = [];
        args.push('--no-output');

        if (port) {
            args.push('--connect');
            args.push(String(port));
        }

        args.push('--display');
        args.push(display_arg);

        args = state.as_args(args);

        return run.haxe(args);
    }

}
<|endoftext|>


<commit_before>module.util.locator = def(
  [
  ],

  function () {
    var browser = function () {
      var scripts = document.getElementsByTagName("script");
      return scripts[scripts.length - 1].src;
    };

    var runtime = module.runtime.locate;

    var locate = function () {
        var f = runtime || browser;
        return f();
    };

    return {
      locate: locate
    };
  }
);
<commit_msg>Whitespace<commit_after>module.util.locator = def(
  [
  ],

  function () {
    var browser = function () {
      var scripts = document.getElementsByTagName("script");
      return scripts[scripts.length - 1].src;
    };

    var runtime = module.runtime.locate;

    var locate = function () {
      var f = runtime || browser;
      return f();
    };

    return {
      locate: locate
    };
  }
);
<|endoftext|>


<commit_before>const webpack = require('webpack')
const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const IgnoreAssetsWebpackPlugin = require('@goldinteractive/ignore-assets-webpack-plugin')
const jsonImporter = require('node-sass-json-importer')
const dotenv = require('dotenv')

const appConfiguration = require('./app-configuration')

const frontendFolder = 'frontend'

const root = path.join(__dirname, '..')
const base = path.join(root, frontendFolder)
const jsBase = path.join(base, 'js')
const cssBase = path.join(base, 'css')
const publicPath = path.join(base, '_public')

const ASSET_HASH_REGEX = '@ASSET_HASH'
// which file types should be checked for asset hash regex?
const ASSET_HASH_REPLACEMENT_FILE_TYPES_WHITELIST = [
  '.html',
  '.twig',
  '.php',
  '.js',
  '.jsx',
  '.css'
]

const sassLoader = {
  loader: 'sass-loader',
  options: {
    includePaths: [cssBase, 'node_modules'],
    importer: jsonImporter
  }
}

const postcssLoader = {
  loader: 'postcss-loader',
  options: {
    config: {
      path: '.config/postcss.config.js'
    }
  }
}

// Note that svg fonts won't be picked up by this loader
const fontLoader = () => ({
  test: /\.(ttf|eot|woff|woff2)$/,
  use: {
    loader: 'file-loader',
    options: {
      name: 'fonts/[name].[ext]'
    }
  }
})

const imageLoader = ({ isProd, assetHash }) => ({
  test: /\.(gif|png|jpe?g|svg)$/i,
  use: [
    {
      loader: 'file-loader',
      options: {
        name: isProd ? '[hash].[ext]' : '[path][name].[ext]',
        outputPath: '/files/',
        publicPath: assetHash + '/files/',
        context: 'frontend'
      }
    },
    {
      loader: 'image-webpack-loader',
      options: {
        disable: true, // disabled in dev mode
        optipng: {
          enabled: false
        },
        pngquant: {
          quality: '90-95'
        }
      }
    }
  ]
})

const buildBaseConfig = ({ isProd }) => ({
  watch: !isProd,
  bail: isProd,
  target: 'web',
  performance: {
    maxEntrypointSize: 700000,
    maxAssetSize: 700000
  },
  stats: isProd ? 'minimal' : 'normal'
})

const pushIfSet = (bool, entry, array = []) => {
  if (bool) {
    return array.concat([entry])
  }
  return array
}

const buildBasePlugins = ({ isProd }) =>
  pushIfSet(
    isProd,
    new webpack.BannerPlugin({
      banner: `Gold Interactive GmbH - www.goldinteractive.ch - ${new Date().getFullYear()}`
    })
  )

const buildCssConfig = (cssEntry, { assetHash, isProd, assetDir }) => ({
  ...buildBaseConfig({
    isProd
  }),
  entry: {
    [cssEntry]: path.join(cssBase, cssEntry + '.scss')
  },
  resolve: {
    modules: [cssBase, base, 'node_modules']
  },
  output: {
    filename: '[name].js',
    path: assetDir
  },
  module: {
    rules: [
      {
        test: /\.s?css$/,
        use: [
          'file-loader?name=[name].css',
          'extract-loader',
          'css-loader',
          postcssLoader,
          sassLoader
        ]
      },
      fontLoader(),
      imageLoader({ isProd, assetHash })
    ]
  },
  plugins: [
    ...buildBasePlugins({
      isProd
    }),
    new IgnoreAssetsWebpackPlugin({
      ignore: cssEntry + '.js'
    })
  ]
})

const buildJsConfig = (jsEntry, { assetHash, isProd, assetDir }) => ({
  ...buildBaseConfig({
    isProd
  }),
  entry: {
    [jsEntry]: path.join(jsBase, jsEntry + '.js')
  },
  resolve: {
    extensions: ['.js', '.json', '.jsx'],
    modules: [jsBase, base, 'node_modules']
  },
  output: {
    filename: '[name].js',
    path: assetDir
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        options: {
          cacheDirectory: true
        }
      },
      {
        test: /\.s?css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          postcssLoader,
          sassLoader
        ]
      },
      fontLoader(),
      imageLoader({ isProd, assetHash })
    ]
  },
  plugins: [
    ...buildBasePlugins({
      isProd
    }),
    new MiniCssExtractPlugin({
      filename: '[name].css'
    })
  ]
})

const buildProjectSkeletonConfig = ({
  jsEntries,
  assetHash,
  isProd,
  baseOutputDir,
  assetDir,
  assetHashTemplateReplacePath
}) => ({
  ...buildBaseConfig({
    isProd
  }),
  entry: {
    // Webpack needs an entry...
    [jsEntries[0] + '-omit']: path.join(jsBase, jsEntries[0] + '.js')
  },
  output: {
    filename: '[name].js',
    path: assetDir
  },
  module: {
    rules: [
      {
        // match all
        test: /[\s\S]*/,
        use: 'null-loader'
      }
    ]
  },
  plugins: [
    new IgnoreAssetsWebpackPlugin({
      ignore: jsEntries[0] + '-omit.js'
    }),
    ...buildBasePlugins({
      isProd
    }),
    new CopyWebpackPlugin([
      {
        from: publicPath,
        to: '..',
        transform: (content, pathname) => {
          if (assetHashTemplateReplacePath && typeof assetHashTemplateReplacePath === 'string') {
            const fullPath = path.join(root, assetHashTemplateReplacePath)
            // One must not stringify binary files such as png, glb, etc.
            const isInFileTypeWhiteList =
              ASSET_HASH_REPLACEMENT_FILE_TYPES_WHITELIST.find(fileType =>
                pathname.endsWith(fileType)
              ) !== undefined
            if (isInFileTypeWhiteList && pathname.startsWith(fullPath)) {
              const regex = new RegExp(ASSET_HASH_REGEX, 'g')
              return content.toString().replace(regex, assetHash)
            }
          }
          return content
        }
      }
    ])
  ]
})

module.exports = env => {
  const isProd = env.mode === 'production'
  const assetHash = env.assetHash
  const environment = env.environment
  const publicDest = env.publicDest
  const assetHashTemplateReplacePath = env.assetHashTemplateReplacePath

  // parses current .env file and provides all variables in process.env.XYZ
  // usage: process.env.APP_URL
  dotenv.config({
    path: path.join(base, '.env.' + environment)
  })

  const baseOutputDir = path.join(root, publicDest)
  const assetDir = baseOutputDir + '/' + assetHash
  const { jsEntries, cssEntries } = appConfiguration(env)

  const configObject = {
    baseOutputDir,
    assetDir,
    assetHash,
    assetHashTemplateReplacePath,
    isProd,
    jsEntries
  }

  return [
    buildProjectSkeletonConfig(configObject),
    ...jsEntries.map(jsEntry => buildJsConfig(jsEntry, configObject)),
    ...cssEntries.map(cssEntry => buildCssConfig(cssEntry, configObject))
  ]
}
<commit_msg>Apply formatter<commit_after>const webpack = require('webpack')
const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const IgnoreAssetsWebpackPlugin = require('@goldinteractive/ignore-assets-webpack-plugin')
const jsonImporter = require('node-sass-json-importer')
const dotenv = require('dotenv')

const appConfiguration = require('./app-configuration')

const frontendFolder = 'frontend'

const root = path.join(__dirname, '..')
const base = path.join(root, frontendFolder)
const jsBase = path.join(base, 'js')
const cssBase = path.join(base, 'css')
const publicPath = path.join(base, '_public')

const ASSET_HASH_REGEX = '@ASSET_HASH'
// which file types should be checked for asset hash regex?
const ASSET_HASH_REPLACEMENT_FILE_TYPES_WHITELIST = [
  '.html',
  '.twig',
  '.php',
  '.js',
  '.jsx',
  '.css'
]

const sassLoader = {
  loader: 'sass-loader',
  options: {
    includePaths: [cssBase, 'node_modules'],
    importer: jsonImporter
  }
}

const postcssLoader = {
  loader: 'postcss-loader',
  options: {
    config: {
      path: '.config/postcss.config.js'
    }
  }
}

// Note that svg fonts won't be picked up by this loader
const fontLoader = () => ({
  test: /\.(ttf|eot|woff|woff2)$/,
  use: {
    loader: 'file-loader',
    options: {
      name: 'fonts/[name].[ext]'
    }
  }
})

const imageLoader = ({ isProd, assetHash }) => ({
  test: /\.(gif|png|jpe?g|svg)$/i,
  use: [
    {
      loader: 'file-loader',
      options: {
        name: isProd ? '[hash].[ext]' : '[path][name].[ext]',
        outputPath: '/files/',
        publicPath: assetHash + '/files/',
        context: 'frontend'
      }
    },
    {
      loader: 'image-webpack-loader',
      options: {
        disable: true, // disabled in dev mode
        optipng: {
          enabled: false
        },
        pngquant: {
          quality: '90-95'
        }
      }
    }
  ]
})

const buildBaseConfig = ({ isProd }) => ({
  watch: !isProd,
  bail: isProd,
  target: 'web',
  performance: {
    maxEntrypointSize: 700000,
    maxAssetSize: 700000
  },
  stats: isProd ? 'minimal' : 'normal'
})

const pushIfSet = (bool, entry, array = []) => {
  if (bool) {
    return array.concat([entry])
  }
  return array
}

const buildBasePlugins = ({ isProd }) =>
  pushIfSet(
    isProd,
    new webpack.BannerPlugin({
      banner: `Gold Interactive GmbH - www.goldinteractive.ch - ${new Date().getFullYear()}`
    })
  )

const buildCssConfig = (cssEntry, { assetHash, isProd, assetDir }) => ({
  ...buildBaseConfig({
    isProd
  }),
  entry: {
    [cssEntry]: path.join(cssBase, cssEntry + '.scss')
  },
  resolve: {
    modules: [cssBase, base, 'node_modules']
  },
  output: {
    filename: '[name].js',
    path: assetDir
  },
  module: {
    rules: [
      {
        test: /\.s?css$/,
        use: [
          'file-loader?name=[name].css',
          'extract-loader',
          'css-loader',
          postcssLoader,
          sassLoader
        ]
      },
      fontLoader(),
      imageLoader({ isProd, assetHash })
    ]
  },
  plugins: [
    ...buildBasePlugins({
      isProd
    }),
    new IgnoreAssetsWebpackPlugin({
      ignore: cssEntry + '.js'
    })
  ]
})

const buildJsConfig = (jsEntry, { assetHash, isProd, assetDir }) => ({
  ...buildBaseConfig({
    isProd
  }),
  entry: {
    [jsEntry]: path.join(jsBase, jsEntry + '.js')
  },
  resolve: {
    extensions: ['.js', '.json', '.jsx'],
    modules: [jsBase, base, 'node_modules']
  },
  output: {
    filename: '[name].js',
    path: assetDir
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        options: {
          cacheDirectory: true
        }
      },
      {
        test: /\.s?css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          postcssLoader,
          sassLoader
        ]
      },
      fontLoader(),
      imageLoader({ isProd, assetHash })
    ]
  },
  plugins: [
    ...buildBasePlugins({
      isProd
    }),
    new MiniCssExtractPlugin({
      filename: '[name].css'
    })
  ]
})

const buildProjectSkeletonConfig = ({
  jsEntries,
  assetHash,
  isProd,
  baseOutputDir,
  assetDir,
  assetHashTemplateReplacePath
}) => ({
  ...buildBaseConfig({
    isProd
  }),
  entry: {
    // Webpack needs an entry...
    [jsEntries[0] + '-omit']: path.join(jsBase, jsEntries[0] + '.js')
  },
  output: {
    filename: '[name].js',
    path: assetDir
  },
  module: {
    rules: [
      {
        // match all
        test: /[\s\S]*/,
        use: 'null-loader'
      }
    ]
  },
  plugins: [
    new IgnoreAssetsWebpackPlugin({
      ignore: jsEntries[0] + '-omit.js'
    }),
    ...buildBasePlugins({
      isProd
    }),
    new CopyWebpackPlugin([
      {
        from: publicPath,
        to: '..',
        transform: (content, pathname) => {
          if (
            assetHashTemplateReplacePath &&
            typeof assetHashTemplateReplacePath === 'string'
          ) {
            const fullPath = path.join(root, assetHashTemplateReplacePath)
            // One must not stringify binary files such as png, glb, etc.
            const isInFileTypeWhiteList =
              ASSET_HASH_REPLACEMENT_FILE_TYPES_WHITELIST.find(fileType =>
                pathname.endsWith(fileType)
              ) !== undefined
            if (isInFileTypeWhiteList && pathname.startsWith(fullPath)) {
              const regex = new RegExp(ASSET_HASH_REGEX, 'g')
              return content.toString().replace(regex, assetHash)
            }
          }
          return content
        }
      }
    ])
  ]
})

module.exports = env => {
  const isProd = env.mode === 'production'
  const assetHash = env.assetHash
  const environment = env.environment
  const publicDest = env.publicDest
  const assetHashTemplateReplacePath = env.assetHashTemplateReplacePath

  // parses current .env file and provides all variables in process.env.XYZ
  // usage: process.env.APP_URL
  dotenv.config({
    path: path.join(base, '.env.' + environment)
  })

  const baseOutputDir = path.join(root, publicDest)
  const assetDir = baseOutputDir + '/' + assetHash
  const { jsEntries, cssEntries } = appConfiguration(env)

  const configObject = {
    baseOutputDir,
    assetDir,
    assetHash,
    assetHashTemplateReplacePath,
    isProd,
    jsEntries
  }

  return [
    buildProjectSkeletonConfig(configObject),
    ...jsEntries.map(jsEntry => buildJsConfig(jsEntry, configObject)),
    ...cssEntries.map(cssEntry => buildCssConfig(cssEntry, configObject))
  ]
}
<|endoftext|>


<commit_before>/**
 * Hooks into `require()` to watch for modifications of the required
 * file. If a modification is detected, the process exits with code
 * `101`.
 */

/**
 * Module dependencies.
 */
var fs = require('fs');
var Path = require('path');

/**
 * Watches the given module's filename.
 */
function watch(module) {
  if (!module.loaded) {
    fs.watchFile(module.filename, {interval : 500}, function(cur, prev) {
      if (cur && +cur.mtime !== +prev.mtime) {
        process.exit(101);
      }
    });
  }
}

/**
 * This is how the argv array looks like:
 * `['node', '/path/to/wrapper.js', '--option1', '--optionN', 'script', 'arg1', 'argN']`
 * ... so we remove ourself:
 */
process.argv.splice(1, 1);

/** Find the first arg that is not an option, starting at index 1 */
var arg;
for (var i=1; i < process.argv.length; i++) {
  arg = process.argv[i];
  if (!/^-/.test(arg)) {
    break;
  }
}

/** Resolve the location of the main script relative to cwd */
var main = Path.resolve(process.cwd(), arg);

if (Path.extname(main) == '.coffee') {
  require('coffee-script');
}

/** Hook into `require()` */
function hookInto(ext) {
  var extensionHandler = require.extensions[ext];
  require.extensions[ext] = function(module, filename) {
    if (module.id == main) {
      module.id = '.';
      module.parent = null;
    }
    watch(module);
    extensionHandler(module, filename);
    if (ext == '.js' && Path.basename(filename, ext) == 'coffee-script') {
      hookInto('.coffee');
    }
  };
}

hookInto('.js');

/** Load the wrapped script */
require(main);<commit_msg>Support require.main by setting process.mainModule. Closes #13<commit_after>/**
 * Hooks into `require()` to watch for modifications of the required
 * file. If a modification is detected, the process exits with code
 * `101`.
 */

/**
 * Module dependencies.
 */
var fs = require('fs');
var Path = require('path');

/**
 * Watches the given module's filename.
 */
function watch(module) {
  if (!module.loaded) {
    fs.watchFile(module.filename, {interval : 500}, function(cur, prev) {
      if (cur && +cur.mtime !== +prev.mtime) {
        process.exit(101);
      }
    });
  }
}

/**
 * This is how the argv array looks like:
 * `['node', '/path/to/wrapper.js', '--option1', '--optionN', 'script', 'arg1', 'argN']`
 * ... so we remove ourself:
 */
process.argv.splice(1, 1);

/** Find the first arg that is not an option, starting at index 1 */
var arg;
for (var i=1; i < process.argv.length; i++) {
  arg = process.argv[i];
  if (!/^-/.test(arg)) {
    break;
  }
}

/** Resolve the location of the main script relative to cwd */
var main = Path.resolve(process.cwd(), arg);

if (Path.extname(main) == '.coffee') {
  require('coffee-script');
}

/** Hook into `require()` */
function hookInto(ext) {
  var extensionHandler = require.extensions[ext];
  require.extensions[ext] = function(module, filename) {
    if (module.id == main) {
      module.id = '.';
      module.parent = null;
      process.mainModule = module;
    }
    watch(module);
    extensionHandler(module, filename);
    if (ext == '.js' && Path.basename(filename, ext) == 'coffee-script') {
      hookInto('.coffee');
    }
  };
}

hookInto('.js');

/** Load the wrapped script */
require(main);<|endoftext|>


<commit_before>function KIFNode(kifExpressions) {
  this.type = 'KIFNode';
  this.expressions = this.expressions || [];
  this.expressions = this.expressions.concat(kifExpressions);
}

function WordNode(identifier) {
  this.type = 'WordNode';
  this.word = identifier;
}

function VariableNode(identifier, variableType) {
  this.type = 'VariableNode';
  this.variableType = variableType || 'IND';
  this.variableName = identifier;
}

function FunctionTermNode(funcName, argsList) {
  this.type = 'FunctionTermNode';
  this.functionName = funcName;
  this.functionArgumentList = this.functionArgumentList || [];
  this.functionArgumentList = this.functionArgumentList.concat(argsList);
}

function EquationNode(firstTerm, secondTerm) {
  this.type = 'EquationNode';
  this.terms = this.terms || [];
  this.terms = this.terms.concat(firstTerm, secondTerm);
}

function StringLiteralNode(rawString) {
  this.type = 'StringLiteralNode';
  this.rawString = rawString;
  this.chars = rawString.substring(1, rawString.length - 1);
}

module.exports = {
  KIFNode: KIFNode,
  WordNode: WordNode,
  VariableNode: VariableNode,
  StringLiteralNode: StringLiteralNode,
  FunctionTermNode: FunctionTermNode,
  EquationNode: EquationNode
};
<commit_msg>Add NumericLiteralNode to ast constructors<commit_after>function KIFNode(kifExpressions) {
  this.type = 'KIFNode';
  this.expressions = this.expressions || [];
  this.expressions = this.expressions.concat(kifExpressions);
}

function WordNode(identifier) {
  this.type = 'WordNode';
  this.word = identifier;
}

function VariableNode(identifier, variableType) {
  this.type = 'VariableNode';
  this.variableType = variableType || 'IND';
  this.variableName = identifier;
}

function FunctionTermNode(funcName, argsList) {
  this.type = 'FunctionTermNode';
  this.functionName = funcName;
  this.functionArgumentList = this.functionArgumentList || [];
  this.functionArgumentList = this.functionArgumentList.concat(argsList);
}

function EquationNode(firstTerm, secondTerm) {
  this.type = 'EquationNode';
  this.terms = this.terms || [];
  this.terms = this.terms.concat(firstTerm, secondTerm);
}

function StringLiteralNode(rawString) {
  this.type = 'StringLiteralNode';
  this.rawString = rawString;
  this.chars = rawString.substring(1, rawString.length - 1);
}

function NumericLiteralNode(rawNumber) {
  this.type = 'NumericLiteralNode';
  this.number = +rawNumber;
}

module.exports = {
  KIFNode: KIFNode,
  WordNode: WordNode,
  VariableNode: VariableNode,
  StringLiteralNode: StringLiteralNode,
  NumericLiteralNode: NumericLiteralNode,
  FunctionTermNode: FunctionTermNode,
  EquationNode: EquationNode
};
<|endoftext|>


<commit_before>/**
 * https://github.com/MarcDiethelm/terrificjs-extensions
 * Adds some sugar and enhancements to @brunschgi's excellent Terrificjs frontend framework.
 * @file terrificjs-extensions.js
 * @license MIT
 * @copyright 2014 Marc Diethelm
 */

(function ($) {

	'use strict';

	/**
	 * Select elements in the module context. Usage: this.$(selector)
	 * @author Marc Diethelm <marc.diethelm@namics.com>
	 * @param {string} selector
	 * @returns {object} - jQuery collection
	 */
	Tc.Module.prototype.$ = function $$(selector) {
		return this.$ctx.find(selector);
	};

	/**
	 * Deprecated. Use Tc.Module.prototype.$
	 * Select elements in the module context. Usage: this.$$(selector)
	 * @deprecated Use Tc.Module.prototype.$
	 * @see Tc.Module.prototype.$
	 * @author Marc Diethelm <marc.diethelm@namics.com>
	 * @param {string} selector
	 * @returns {object} - jQuery collection
	 */
	Tc.Module.prototype.$$ = Tc.Module.prototype.$;

	/**
	 * Bind methods to Terrific module context. Usage: this.bindAll(funcName [,funcName...])
	 * Inspired by Underscore's bindAll. http://underscorejs.org/#bindAll
	 * @author Marc Diethelm <marc.diethelm@namics.com>
	 * @author Simon Harte <simon.harte@namics.com>
	 * @param {...string} methods - Names of methods each as a param.
	 * @return {object} - Returns the module instance for chaining.
	 */
	Tc.Module.prototype.bindAll = function bindAll(methods) {
		var i = 0,
			args = arguments,
			argLen = args.length,
			methodName
			;

		for (i; i < argLen; i++) {
			methodName = args[i];
			if (typeof this[methodName] === 'function') {
				this[methodName] = $.proxy(this, methodName);
			} else if (typeof methodName === 'string') {
				throw new TypeError('bindAll: Tc.Module.' + this.getName() + '.' + methodName + ' is not a function');
			} else {
				throw new TypeError('Arguments to bindAll must be strings');
			}
		}

		return this;
	};

	/**
	 * Get the name of the Terrific module
	 * @author Remo Brunschwiler <remo.brunschwiler@namics.com>
	 * @author Mathias Hayoz <mathias.hayoz@namics.com>
	 * @returns {string} - Module name
	 */
	Tc.Module.prototype.getName = function getName() {
		var property;
		if (!this._modName) {
			for (property in Tc.Module) {
				if (Tc.Module.hasOwnProperty(property) && property !== 'constructor' && this instanceof Tc.Module[property]) {
					this._modName = property;
					break;
				}
			}
		}

		return this._modName;
	};

	/**
	 * Simplify connector channel subscription. Usage: this.subscribe(channelName [,channelName...])
	 *
	 * Because the second parameter to sandbox.subscribe `this` is often forgotten.
	 * Additionally this method allows connecting to multiple channels at once.
	 * @author Simon Harte <simon.harte@namics.com>
	 * @param {...string} channels - Connector channels to subscribe to
	 * @return {object} - Returns the module instance for chaining
	 */
	Tc.Module.prototype.subscribe = function subscribe(channels) {
		var i = 0,
			args = arguments,
			argLen = args.length
			;

		for (i; i < argLen; i++) {
			this.sandbox.subscribe(args[i], this);
		}

		return this;
	};

	var tplCache = {};
	/**
	 * Micro-templating for modules. Extrapolates {{= foo }} variables in strings from data.
	 * This function is a remix of
	 * - Simple JavaScript Templating – John Resig - http://ejohn.org/ - MIT Licensed
	 * - https://gist.github.com/topliceanu/1537847
	 * - http://weblog.west-wind.com/posts/2008/Oct/13/Client-Templating-with-jQuery
	 * This code incorporates a fix for single-quote usage.
	 * @author Marc Diethelm <marc.diethelm@namics.com>
	 * @param {string} str - Template
	 * @param {object} [data] - Optional, renders template immediately if present. Data to use as the template context for variable extrapolation.
	 * @returns {function|string} - Template function, to render template with data, or if data was supplied already the rendered template.
	 */
	Tc.Module.prototype.template = function template(str, data) {

		// Figure out if we're getting a template, or if we need to
		// load the template - and be sure to cache the result.
		var fn = !/\W/.test(str) ?
			tplCache[str] = tplCache[str] ||
				template(document.getElementById(str).innerHTML) :
			// Generate a reusable function that will serve as a template
			// generator (and which will be cached).
			/*jshint -W054, -W014 */
			new Function("obj",
					"var p=[],print=function(){p.push.apply(p,arguments);};" +
					// Introduce the data as local variables using with(){}
					"with(obj){p.push('" +
					// Convert the template into pure JavaScript
					str.replace(/[\r\t\n]/g, " ")
						.replace(/'(?=[^%]*\}\}>)/g, "\t")
						.split("'").join("\\'")
						.split("\t").join("'")
						.replace(/\{\{=(.+?)\}\}/g, "',$1,'")
						.split("{{").join("');")
						.split("}}").join("p.push('")
					+ "');}return p.join('');");
		/*jshint +W054, +W014 */
		// Provide some basic currying to the user
		return data ? fn(data) : fn;
	};

})($ || jQuery);
<commit_msg>returns not return<commit_after>/**
 * https://github.com/MarcDiethelm/terrificjs-extensions
 * Adds some sugar and enhancements to @brunschgi's excellent Terrificjs frontend framework.
 * @file terrificjs-extensions.js
 * @license MIT
 * @copyright 2014 Marc Diethelm
 */

(function ($) {

	'use strict';

	/**
	 * Select elements in the module context. Usage: this.$(selector)
	 * @author Marc Diethelm <marc.diethelm@namics.com>
	 * @param {string} selector
	 * @returns {object} - jQuery collection
	 */
	Tc.Module.prototype.$ = function $$(selector) {
		return this.$ctx.find(selector);
	};

	/**
	 * Deprecated. Use Tc.Module.prototype.$
	 * Select elements in the module context. Usage: this.$$(selector)
	 * @deprecated Use Tc.Module.prototype.$
	 * @see Tc.Module.prototype.$
	 * @author Marc Diethelm <marc.diethelm@namics.com>
	 * @param {string} selector
	 * @returns {object} - jQuery collection
	 */
	Tc.Module.prototype.$$ = Tc.Module.prototype.$;

	/**
	 * Bind methods to Terrific module context. Usage: this.bindAll(funcName [,funcName...])
	 * Inspired by Underscore's bindAll. http://underscorejs.org/#bindAll
	 * @author Marc Diethelm <marc.diethelm@namics.com>
	 * @author Simon Harte <simon.harte@namics.com>
	 * @param {...string} methods - Names of methods each as a param.
	 * @returns {object} module - Returns the module instance for chaining.
	 */
	Tc.Module.prototype.bindAll = function bindAll(methods) {
		var i = 0,
			args = arguments,
			argLen = args.length,
			methodName
			;

		for (i; i < argLen; i++) {
			methodName = args[i];
			if (typeof this[methodName] === 'function') {
				this[methodName] = $.proxy(this, methodName);
			} else if (typeof methodName === 'string') {
				throw new TypeError('bindAll: Tc.Module.' + this.getName() + '.' + methodName + ' is not a function');
			} else {
				throw new TypeError('Arguments to bindAll must be strings');
			}
		}

		return this;
	};

	/**
	 * Get the name of the Terrific module
	 * @author Remo Brunschwiler <remo.brunschwiler@namics.com>
	 * @author Mathias Hayoz <mathias.hayoz@namics.com>
	 * @returns {string} - Module name
	 */
	Tc.Module.prototype.getName = function getName() {
		var property;
		if (!this._modName) {
			for (property in Tc.Module) {
				if (Tc.Module.hasOwnProperty(property) && property !== 'constructor' && this instanceof Tc.Module[property]) {
					this._modName = property;
					break;
				}
			}
		}

		return this._modName;
	};

	/**
	 * Simplify connector channel subscription. Usage: this.subscribe(channelName [,channelName...])
	 *
	 * Because the second parameter to sandbox.subscribe `this` is often forgotten.
	 * Additionally this method allows connecting to multiple channels at once.
	 * @author Simon Harte <simon.harte@namics.com>
	 * @param {...string} channels - Connector channels to subscribe to
	 * @returns {object} module - Returns the module instance for chaining
	 */
	Tc.Module.prototype.subscribe = function subscribe(channels) {
		var i = 0,
			args = arguments,
			argLen = args.length
			;

		for (i; i < argLen; i++) {
			this.sandbox.subscribe(args[i], this);
		}

		return this;
	};

	var tplCache = {};
	/**
	 * Micro-templating for modules. Extrapolates {{= foo }} variables in strings from data.
	 * This function is a remix of
	 * - Simple JavaScript Templating – John Resig - http://ejohn.org/ - MIT Licensed
	 * - https://gist.github.com/topliceanu/1537847
	 * - http://weblog.west-wind.com/posts/2008/Oct/13/Client-Templating-with-jQuery
	 * This code incorporates a fix for single-quote usage.
	 * @author Marc Diethelm <marc.diethelm@namics.com>
	 * @param {string} str - Template
	 * @param {object} [data] - Optional, renders template immediately if present. Data to use as the template context for variable extrapolation.
	 * @returns {function|string} - Template function, to render template with data, or if data was supplied already the rendered template.
	 */
	Tc.Module.prototype.template = function template(str, data) {

		// Figure out if we're getting a template, or if we need to
		// load the template - and be sure to cache the result.
		var fn = !/\W/.test(str) ?
			tplCache[str] = tplCache[str] ||
				template(document.getElementById(str).innerHTML) :
			// Generate a reusable function that will serve as a template
			// generator (and which will be cached).
			/*jshint -W054, -W014 */
			new Function("obj",
					"var p=[],print=function(){p.push.apply(p,arguments);};" +
					// Introduce the data as local variables using with(){}
					"with(obj){p.push('" +
					// Convert the template into pure JavaScript
					str.replace(/[\r\t\n]/g, " ")
						.replace(/'(?=[^%]*\}\}>)/g, "\t")
						.split("'").join("\\'")
						.split("\t").join("'")
						.replace(/\{\{=(.+?)\}\}/g, "',$1,'")
						.split("{{").join("');")
						.split("}}").join("p.push('")
					+ "');}return p.join('');");
		/*jshint +W054, +W014 */
		// Provide some basic currying to the user
		return data ? fn(data) : fn;
	};

})($ || jQuery);
<|endoftext|>


<commit_before>/*
*
 * svg-gallery.js: a new svg gallery
 *
 * 2013-10-31
 *
 * By dredtrake@gmail.com
 *
 * Public Domain.
 * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
 */
'use strict';
var SvgGallery = (function(JQUERY, SVG){
	var SvgGallery = function (params){
		var defaults = {
					_item : 'canvas',
					_dataURL : '',
					_data : '',
					_folderSrc : '',
					_width : '1920',
					_height : '1080',
					_preserveAspectRatio : "xMidYMid slice",
					_transition : "squares",
					onclick : function(){ return false},
					_duration : 650,
					_animationUpType : ">",
					_animationDownType : "<",
					_order : 'desc',
					_loop : false,
					onanimate : function (){return false;},
					ready : function (){return false;}
				};
		this.options = JQUERY.extend({}, defaults, params);
		this.images = [];
		this.draw = '';
		this.i = null;
	};
	SvgGallery.prototype = {
		constructor : SvgGallery,
		options : {},
		//~ draw : null,
		svg : null,
		_width : 0,
		_height : 0,
		diag : null,
		circ : null,
		rect : null,
		_angle : null,
		_isSliding : 0,
		_maxSliding : null,
		isLocalStorage : 0,
		simpleUp : 0,
		init : function init (){
			if(!this.options._dataURL && !this.options._data) {
				$("#"+this.options._item).html('
Please feed me with some yummy json!!
');
				return;
			}
			this._width = this.options._width;
			this._height = this.options._height;
			this._angle = this.getAngle(0, this._height, this._width, 0);
			this.draw = SVG(this.options._item);
			this.svg = JQUERY('#'+this.options._item).find('svg')[0];
			this.svg.setAttribute('viewBox', '0 0 '+this._width+' '+this._height);
			this.svg.setAttribute('preserveAspectRatio', this.options._preserveAspectRatio);
			var _this = this;
			if(this.options._data){
				this._maxSliding = this.options._data.length;
				this.drawScene(this.options._data);
			}else{
				JQUERY.ajax({
					url : _this.options._dataURL,
					type:"get",
					dataType:"json",
					success:function (e){
						_this._maxSliding = e.length;
						_this.drawScene(e);
					}
				});
			}
		},
		// TODO : add a onload images listener.
		// run bindMouseWheel on this event...
		//~ ADD Loop event
		drawScene : function drawScene (_e){
			var _l = _e.length;
			for(this.i= 0; this.i < _l; ++this.i){
				var _prefixe = this.options._folderSrc || "";
				this.images[this.i] = this.draw.image(_prefixe+_e[this.i].img_src, this._width, this._height);
				this.images[this.i].style('cursor', 'pointer');
				this.images[this.i].data('id', _e[this.i].id);
				this.images[this.i].data('nom', _e[this.i].nom);
				this.images[this.i].data('description', _e[this.i].description);
				this.images[this.i].click(this.options.onclick);
			}
			this.i -= 1;
			this.circ = this.draw.circle(.2);
			this.circ.back();
			this.rect = this.draw.rect(.2, .2);
			this.rect.back();
			this.diag = this.draw.rect(.2, this._height);
			this.diag.back();
			this.bindMouseWheel();
			this.options.ready();
		},
		extractDelta : function extractDelta (_e){
			if (_e.wheelDelta)	return _e.wheelDelta;
			if (_e.detail)		return _e.detail * -40;
			if (_e.originalEvent && _e.originalEvent.wheelDelta)	return _e.originalEvent.wheelDelta;
		},
		getAngle : function getAngle(x1,y1,x2,y2){
			var angle = Math.atan((x2-x1)/(y1-y2))/(Math.PI/180);
			angle = Math.round(angle);
			if ( angle > 0 ){
				 if (y1 < y2){
					return angle;
				 }else{
					return 180 + angle;
				 }
			} else {
				if (x1 < x2){
					return 180 + angle;
				}else{
					return 360 + angle;
				}
			}
		},
		bindMouseWheel : function bindMouseWheel (){
			if (this.svg.addEventListener) {
				// IE9, Chrome, Safari, Opera
				this.svg.addEventListener("mousewheel", this.animateGallery.bind(this), false);
				//~ // Firefox
				this.svg.addEventListener("DOMMouseScroll", this.animateGallery.bind(this), false);
			}
			// IE 6/7/8
			else{
				this.svg.attachEvent("onmousewheel", this.animateGallery.bind(this));
			}
		},
		animateGallery : function (_e){
			var _delta = this.extractDelta(_e);
			switch(this.options._transition){
				case "diagonales" :
					this.diagonales(_delta);
					break;
				case "circles" :
					this.circles(_delta);
					break;
				case "squares" :
					this.squares(_delta);
					break;
				defaults :
					this.diagonales(_delta);
					break;
			}
		},
		diagonales : function diagonales (_delta){
			var _this = this;
			if(this._isSliding){
				return;
			}
			if(_delta < 0){
				if(this.i > 0){
					this._isSliding = 1;
					this.simpleUp = 0;
					--this.i;
					this.diag.attr({'width' : .2, 'height' : this._height})
						.move(this._width, 0)
						.skew(360-this._angle, 0)
					this.images[this.i].clipWith(this.diag).front();
					this.diag.animate(this.options._duration,  this.options._animationDownType)
						.move(0, 0)
						.attr('width', this._width * 2)
						.after(function() {
							this.attr('width', 0);
							_this._isSliding = 0;
							_this.images[_this.i].unclip();
							_this.options.onanimate();
						});
				}else{
					return;
				}
			}else{
				if(this.i == this._maxSliding-1){
					return;
				}
				this._isSliding = 1;
				if(this.simpleUp){
					this.images[this.i+1].front().backward();
				}
				this.images[this.i].clipWith(this.diag);

				this.diag.attr({'width' : this._width*2, 'height' : this._height})
					.move(0, 0)
					.animate(this.options._duration,  this.options._animationUpType)
					.move(this._width, 0)
					.attr('width', .2)
					.after(function() {
						this.attr('width', 0);
						_this.images[_this.i].unclip();
						_this._isSliding = 0;
						++_this.i;
						_this.images[_this.i].front();
						_this.options.onanimate();
					});
				this.simpleUp = 1;
			}
		},
		circles : function circles (_delta){
			var _this = this;
			if(this._isSliding){
				return;
			}
			if(_delta < 0){
				if(this.i > 0){
					this._isSliding = 1;
					this.simpleUp = 0;
					--this.i;
					this.circ.attr('rx', .2)
						.attr('ry', .2)
					this.circ.center(.1, .1)
						.move(this._width/2, this._height/2)
					this.images[this.i].clipWith(this.circ).front();
					this.circ.animate(this.options._duration, this.options._animationDownType)
						.center(this._width/2, this._height/2)
						.attr('rx', this._width)
						.attr('ry', this._width)
						.after(function() {
							_this._isSliding = 0;
							_this.images[_this.i].unclip();
							this.attr('rx', 0);
							this.attr('ry', 0);
							_this.options.onanimate();
						});
				}else{
					return;
				}
			}else{
				if(this.i == this._maxSliding-1){
					return;
				}
				this._isSliding = 1;
				if(this.simpleUp){
					this.images[this.i+1].front().backward();
				}
				this.images[this.i].clipWith(this.circ);
				this.circ.attr('rx', this._width)
					.attr('ry', this._width)
					.center(this._width/2, this._height/2)
					.animate(this.options._duration,  this.options._animationUpType)
					.center(.1, .1)
					.move(this._width/2, this._height/2)
					.attr('rx', .2)
					.attr('ry', .2)
					.after(function() {
						this.attr('rx', 0);
						this.attr('ry', 0);
						_this.images[_this.i].unclip();
						_this._isSliding = 0;
						++_this.i;
						_this.images[_this.i].front();
						_this.options.onanimate();
					});
				this.simpleUp = 1;
			}
		},
		squares : function squares (_delta){
			var _this = this;
			if(this._isSliding){
				return;
			}
			if(_delta < 0){
				if(this.i > 0){
					this._isSliding = 1;
					this.simpleUp = 0;
					--this.i;
					this.rect.attr({'width' : .2, 'height' : .2})
						.move(this._width/2, this._height/2);
					this.images[this.i].clipWith(this.rect).front();
					this.rect.animate(this.options._duration,  this.options._animationDownType)
						.move(0, -(this._height/2))
						.attr({'width' : this._width, 'height' : this._width})
						.after(function() {
							_this._isSliding = 0;
							_this.images[_this.i].unclip();
							this.attr({'width' : 0, 'height' : 0});
							_this.options.onanimate();
						});
				}else{
					return;
				}
			}else{
				if(this.i == this._maxSliding-1){
					return;
				}
				this._isSliding = 1;
				if(this.simpleUp){
					this.images[this.i+1].front().backward();
				}
				this.images[this.i].clipWith(this.rect);
				this.rect.attr({'width' : this._width, 'height' : this._width})
					.move(0,  -(this._height/2))
					.animate(this.options._duration,  this.options._animationUpType)
					.move(this._width / 2, this._height / 2)
					.attr({'width' : .2, 'height' : .2})
					.after(function() {
						this.attr({'width' : 0, 'height' : 0});
						_this.images[_this.i].unclip();
						_this._isSliding = 0;
						++_this.i;
						_this.images[_this.i].front();
						_this.options.onanimate();
					});
				this.simpleUp = 1;
			}
		},
		bubbles : function (){
			// random bubbles
		},
		swipe : function (direction){
			// swipe as diagonal do, but form a side (up, down, left, right)
		},
		getID : function getID (){
			return this.images[this.i].data('id');
		}
	};
	return SvgGallery;
})($, SVG);<commit_msg>removing lib in example/js<commit_after><|endoftext|>


<commit_before>import _ from 'lodash';

import {
    REMOVE_FILTER,
    ADD_FILTER
} from "../actions/types";

//state is not application state, just the state
//this reducer is responsible for, e.g. creating books
//if state is undefined, set to null

export default function(state = [] , action) {
    switch (action.type) {
        case ADD_FILTER:
            return _.union([...state], [action.payload]);

        case REMOVE_FILTER:
            return _.omit(state, action.payload);

        default:
            return state;
    }

}<commit_msg>filtering<commit_after>import _ from 'lodash';

import {
    REMOVE_FILTER,
    ADD_FILTER
} from "../actions/types";

//state is not application state, just the state
//this reducer is responsible for, e.g. creating books
//if state is undefined, set to null

export default function(state = [] , action) {
    switch (action.type) {
        case ADD_FILTER:
            return _.union([...state], [action.payload]);

        case REMOVE_FILTER:
            return state.filter(item => item !== action.payload);

        default:
            return state;
    }

}<|endoftext|>