<commit_before>'use strict';

var lib = require('./lib');
var r = require('./runtime');

function normalize(value, defaultValue) {
    if(value === null || value === undefined || value === false) {
        return defaultValue;
    }
    return value;
}

var filters = {
    abs: function(n) {
        return Math.abs(n);
    },

    batch: function(arr, linecount, fill_with) {
        var i;
        var res = [];
        var tmp = [];

        for(i = 0; i < arr.length; i++) {
            if(i % linecount === 0 && tmp.length) {
                res.push(tmp);
                tmp = [];
            }

            tmp.push(arr[i]);
        }

        if(tmp.length) {
            if(fill_with) {
                for(i = tmp.length; i < linecount; i++) {
                    tmp.push(fill_with);
                }
            }

            res.push(tmp);
        }

        return res;
    },

    capitalize: function(str) {
        str = normalize(str, '');
        var ret = str.toLowerCase();
        return r.copySafeness(str, ret.charAt(0).toUpperCase() + ret.slice(1));
    },

    center: function(str, width) {
        str = normalize(str, '');
        width = width || 80;

        if(str.length >= width) {
            return str;
        }

        var spaces = width - str.length;
        var pre = lib.repeat(' ', spaces/2 - spaces % 2);
        var post = lib.repeat(' ', spaces/2);
        return r.copySafeness(str, pre + str + post);
    },

    'default': function(val, def, bool) {
        if(bool) {
            return val ? val : def;
        }
        else {
            return (val !== undefined) ? val : def;
        }
    },

    dictsort: function(val, case_sensitive, by) {
        if (!lib.isObject(val)) {
            throw new lib.TemplateError('dictsort filter: val must be an object');
        }

        var array = [];
        for (var k in val) {
            // deliberately include properties from the object's prototype
            array.push([k,val[k]]);
        }

        var si;
        if (by === undefined || by === 'key') {
            si = 0;
        } else if (by === 'value') {
            si = 1;
        } else {
            throw new lib.TemplateError(
                'dictsort filter: You can only sort by either key or value');
        }

        array.sort(function(t1, t2) {
            var a = t1[si];
            var b = t2[si];

            if (!case_sensitive) {
                if (lib.isString(a)) {
                    a = a.toUpperCase();
                }
                if (lib.isString(b)) {
                    b = b.toUpperCase();
                }
            }

            return a > b ? 1 : (a === b ? 0 : -1);
        });

        return array;
    },

    dump: function(obj) {
        return JSON.stringify(obj);
    },

    escape: function(str) {
        if(typeof str === 'string' ||
           str instanceof r.SafeString) {
            return lib.escape(str);
        }
        return str;
    },

    safe: function(str) {
        return r.markSafe(str);
    },

    first: function(arr) {
        return arr[0];
    },

    groupby: function(arr, attr) {
        return lib.groupBy(arr, attr);
    },

    indent: function(str, width, indentfirst) {
        str = normalize(str, '');

        if (str === '') return '';

        width = width || 4;
        var res = '';
        var lines = str.split('\n');
        var sp = lib.repeat(' ', width);

        for(var i=0; i<lines.length; i++) {
            if(i === 0 && !indentfirst) {
                res += lines[i] + '\n';
            }
            else {
                res += sp + lines[i] + '\n';
            }
        }

        return r.copySafeness(str, res);
    },

    join: function(arr, del, attr) {
        del = del || '';

        if(attr) {
            arr = lib.map(arr, function(v) {
                return v[attr];
            });
        }

        return arr.join(del);
    },

    last: function(arr) {
        return arr[arr.length-1];
    },

    length: function(val) {
        var value = normalize(val, '');

        return value !== undefined ? value.length : 0;
    },

    list: function(val) {
        if(lib.isString(val)) {
            return val.split('');
        }
        else if(lib.isObject(val)) {
            var keys = [];

            if(Object.keys) {
                keys = Object.keys(val);
            }
            else {
                for(var k in val) {
                    keys.push(k);
                }
            }

            return lib.map(keys, function(k) {
                return { key: k,
                         value: val[k] };
            });
        }
        else if(lib.isArray(val)) {
          return val;
        }
        else {
            throw new lib.TemplateError('list filter: type not iterable');
        }
    },

    lower: function(str) {
        str = normalize(str, '');
        return str.toLowerCase();
    },

    random: function(arr) {
        return arr[Math.floor(Math.random() * arr.length)];
    },

    rejectattr: function(arr, attr) {
      return arr.filter(function (item) {
        return !item[attr];
      });
    },

    selectattr: function(arr, attr) {
      return arr.filter(function (item) {
        return !!item[attr];
      });
    },

    replace: function(str, old, new_, maxCount) {
        var originalStr = str;

        if (old instanceof RegExp) {
            return str.replace(old, new_);
        }

        if(typeof maxCount === 'undefined'){
            maxCount = -1;
        }

        var res = '';  // Output

        // Cast Numbers in the search term to string
        if(typeof old === 'number'){
            old = old + '';
        }
        else if(typeof old !== 'string') {
            // If it is something other than number or string,
            // return the original string
            return str;
        }

        // Cast numbers in the replacement to string
        if(typeof str === 'number'){
            str = str + '';
        }

        // If by now, we don't have a string, throw it back
        if(typeof str !== 'string' && !(str instanceof r.SafeString)){
            return str;
        }

        // ShortCircuits
        if(old === ''){
            // Mimic the python behaviour: empty string is replaced
            // by replacement e.g. "abc"|replace("", ".") -> .a.b.c.
            res = new_ + str.split('').join(new_) + new_;
            return r.copySafeness(str, res);
        }

        var nextIndex = str.indexOf(old);
        // if # of replacements to perform is 0, or the string to does
        // not contain the old value, return the string
        if(maxCount === 0 || nextIndex === -1){
            return str;
        }

        var pos = 0;
        var count = 0; // # of replacements made

        while(nextIndex  > -1 && (maxCount === -1 || count < maxCount)){
            // Grab the next chunk of src string and add it with the
            // replacement, to the result
            res += str.substring(pos, nextIndex) + new_;
            // Increment our pointer in the src string
            pos = nextIndex + old.length;
            count++;
            // See if there are any more replacements to be made
            nextIndex = str.indexOf(old, pos);
        }

        // We've either reached the end, or done the max # of
        // replacements, tack on any remaining string
        if(pos < str.length) {
            res += str.substring(pos);
        }

        return r.copySafeness(originalStr, res);
    },

    reverse: function(val) {
        var arr;
        if(lib.isString(val)) {
            arr = filters.list(val);
        }
        else {
            // Copy it
            arr = lib.map(val, function(v) { return v; });
        }

        arr.reverse();

        if(lib.isString(val)) {
            return r.copySafeness(val, arr.join(''));
        }
        return arr;
    },

    round: function(val, precision, method) {
        precision = precision || 0;
        var factor = Math.pow(10, precision);
        var rounder;

        if(method === 'ceil') {
            rounder = Math.ceil;
        }
        else if(method === 'floor') {
            rounder = Math.floor;
        }
        else {
            rounder = Math.round;
        }

        return rounder(val * factor) / factor;
    },

    slice: function(arr, slices, fillWith) {
        var sliceLength = Math.floor(arr.length / slices);
        var extra = arr.length % slices;
        var offset = 0;
        var res = [];

        for(var i=0; i<slices; i++) {
            var start = offset + i * sliceLength;
            if(i < extra) {
                offset++;
            }
            var end = offset + (i + 1) * sliceLength;

            var slice = arr.slice(start, end);
            if(fillWith && i >= extra) {
                slice.push(fillWith);
            }
            res.push(slice);
        }

        return res;
    },

    sort: r.makeMacro(['value', 'reverse', 'case_sensitive', 'attribute'], [], function(arr, reverse, caseSens, attr) {
         // Copy it
        arr = lib.map(arr, function(v) { return v; });

        arr.sort(function(a, b) {
            var x, y;

            if(attr) {
                x = a[attr];
                y = b[attr];
            }
            else {
                x = a;
                y = b;
            }

            if(!caseSens && lib.isString(x) && lib.isString(y)) {
                x = x.toLowerCase();
                y = y.toLowerCase();
            }

            if(x < y) {
                return reverse ? 1 : -1;
            }
            else if(x > y) {
                return reverse ? -1: 1;
            }
            else {
                return 0;
            }
        });

        return arr;
    }),

    string: function(obj) {
        return r.copySafeness(obj, obj);
    },

    striptags: function(input, preserve_linebreaks) {
        input = normalize(input, '');
        preserve_linebreaks = preserve_linebreaks || false;
        var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>|/gi;
        var res = '';
        if (preserve_linebreaks) {
            res = filters.trim(input.replace(tags, ''))
                .replace(/^ +| +$/gm, '')     // remove leading and trailing spaces
                .replace(/ +/g, ' ')          // squash adjacent spaces
                .replace(/(\r\n)/g, '\n')     // normalize linebreaks (CRLF -> LF)
                .replace(/\n\n\n+/g, '\n\n'); // squash abnormal adjacent linebreaks
        } else {
            res = filters.trim(input.replace(tags, ''))
                .replace(/\s+/gi, ' ');
        }
        return r.copySafeness(input, res);
    },

    title: function(str) {
        str = normalize(str, '');
        var words = str.split(' ');
        for(var i = 0; i < words.length; i++) {
            words[i] = filters.capitalize(words[i]);
        }
        return r.copySafeness(str, words.join(' '));
    },

    trim: function(str) {
        return r.copySafeness(str, str.replace(/^\s*|\s*$/g, ''));
    },

    truncate: function(input, length, killwords, end) {
        var orig = input;
        input = normalize(input, '');
        length = length || 255;

        if (input.length <= length)
            return input;

        if (killwords) {
            input = input.substring(0, length);
        } else {
            var idx = input.lastIndexOf(' ', length);
            if(idx === -1) {
                idx = length;
            }

            input = input.substring(0, idx);
        }

        input += (end !== undefined && end !== null) ? end : '...';
        return r.copySafeness(orig, input);
    },

    upper: function(str) {
        str = normalize(str, '');
        return str.toUpperCase();
    },

    urlencode: function(obj) {
        var enc = encodeURIComponent;
        if (lib.isString(obj)) {
            return enc(obj);
        } else {
            var parts;
            if (lib.isArray(obj)) {
                parts = obj.map(function(item) {
                    return enc(item[0]) + '=' + enc(item[1]);
                });
            } else {
                parts = [];
                for (var k in obj) {
                    if (obj.hasOwnProperty(k)) {
                        parts.push(enc(k) + '=' + enc(obj[k]));
                    }
                }
            }
            return parts.join('&');
        }
    },

    urlize: function(str, length, nofollow) {
        if (isNaN(length)) length = Infinity;

        var noFollowAttr = (nofollow === true ? ' rel="nofollow"' : '');

        // For the jinja regexp, see
        // https://github.com/mitsuhiko/jinja2/blob/f15b814dcba6aa12bc74d1f7d0c881d55f7126be/jinja2/utils.py#L20-L23
        var puncRE = /^(?:\(|<|<)?(.*?)(?:\.|,|\)|\n|>)?$/;
        // from http://blog.gerv.net/2011/05/html5_email_address_regexp/
        var emailRE = /^[\w.!#$%&'*+\-\/=?\^`{|}~]+@[a-z\d\-]+(\.[a-z\d\-]+)+$/i;
        var httpHttpsRE = /^https?:\/\/.*$/;
        var wwwRE = /^www\./;
        var tldRE = /\.(?:org|net|com)(?:\:|\/|$)/;

        var words = str.split(/\s+/).filter(function(word) {
          // If the word has no length, bail. This can happen for str with
          // trailing whitespace.
          return word && word.length;
        }).map(function(word) {
          var matches = word.match(puncRE);
          var possibleUrl = matches && matches[1] || word;

          // url that starts with http or https
          if (httpHttpsRE.test(possibleUrl))
            return '' + possibleUrl.substr(0, length) + '';

          // url that starts with www.
          if (wwwRE.test(possibleUrl))
            return '' + possibleUrl.substr(0, length) + '';

          // an email address of the form username@domain.tld
          if (emailRE.test(possibleUrl))
            return '' + possibleUrl + '';

          // url that ends in .com, .org or .net that is not an email address
          if (tldRE.test(possibleUrl))
            return '' + possibleUrl.substr(0, length) + '';

          return word;

        });

        return words.join(' ');
    },

    wordcount: function(str) {
        str = normalize(str, '');
        var words = (str) ? str.match(/\w+/g) : null;
        return (words) ? words.length : null;
    },

    'float': function(val, def) {
        var res = parseFloat(val);
        return isNaN(res) ? def : res;
    },

    'int': function(val, def) {
        var res = parseInt(val, 10);
        return isNaN(res) ? def : res;
    }
};

// Aliases
filters.d = filters['default'];
filters.e = filters.escape;

module.exports = filters;
<commit_msg>Refactor `striptags` code a little bit<commit_after>'use strict';

var lib = require('./lib');
var r = require('./runtime');

function normalize(value, defaultValue) {
    if(value === null || value === undefined || value === false) {
        return defaultValue;
    }
    return value;
}

var filters = {
    abs: function(n) {
        return Math.abs(n);
    },

    batch: function(arr, linecount, fill_with) {
        var i;
        var res = [];
        var tmp = [];

        for(i = 0; i < arr.length; i++) {
            if(i % linecount === 0 && tmp.length) {
                res.push(tmp);
                tmp = [];
            }

            tmp.push(arr[i]);
        }

        if(tmp.length) {
            if(fill_with) {
                for(i = tmp.length; i < linecount; i++) {
                    tmp.push(fill_with);
                }
            }

            res.push(tmp);
        }

        return res;
    },

    capitalize: function(str) {
        str = normalize(str, '');
        var ret = str.toLowerCase();
        return r.copySafeness(str, ret.charAt(0).toUpperCase() + ret.slice(1));
    },

    center: function(str, width) {
        str = normalize(str, '');
        width = width || 80;

        if(str.length >= width) {
            return str;
        }

        var spaces = width - str.length;
        var pre = lib.repeat(' ', spaces/2 - spaces % 2);
        var post = lib.repeat(' ', spaces/2);
        return r.copySafeness(str, pre + str + post);
    },

    'default': function(val, def, bool) {
        if(bool) {
            return val ? val : def;
        }
        else {
            return (val !== undefined) ? val : def;
        }
    },

    dictsort: function(val, case_sensitive, by) {
        if (!lib.isObject(val)) {
            throw new lib.TemplateError('dictsort filter: val must be an object');
        }

        var array = [];
        for (var k in val) {
            // deliberately include properties from the object's prototype
            array.push([k,val[k]]);
        }

        var si;
        if (by === undefined || by === 'key') {
            si = 0;
        } else if (by === 'value') {
            si = 1;
        } else {
            throw new lib.TemplateError(
                'dictsort filter: You can only sort by either key or value');
        }

        array.sort(function(t1, t2) {
            var a = t1[si];
            var b = t2[si];

            if (!case_sensitive) {
                if (lib.isString(a)) {
                    a = a.toUpperCase();
                }
                if (lib.isString(b)) {
                    b = b.toUpperCase();
                }
            }

            return a > b ? 1 : (a === b ? 0 : -1);
        });

        return array;
    },

    dump: function(obj) {
        return JSON.stringify(obj);
    },

    escape: function(str) {
        if(typeof str === 'string' ||
           str instanceof r.SafeString) {
            return lib.escape(str);
        }
        return str;
    },

    safe: function(str) {
        return r.markSafe(str);
    },

    first: function(arr) {
        return arr[0];
    },

    groupby: function(arr, attr) {
        return lib.groupBy(arr, attr);
    },

    indent: function(str, width, indentfirst) {
        str = normalize(str, '');

        if (str === '') return '';

        width = width || 4;
        var res = '';
        var lines = str.split('\n');
        var sp = lib.repeat(' ', width);

        for(var i=0; i<lines.length; i++) {
            if(i === 0 && !indentfirst) {
                res += lines[i] + '\n';
            }
            else {
                res += sp + lines[i] + '\n';
            }
        }

        return r.copySafeness(str, res);
    },

    join: function(arr, del, attr) {
        del = del || '';

        if(attr) {
            arr = lib.map(arr, function(v) {
                return v[attr];
            });
        }

        return arr.join(del);
    },

    last: function(arr) {
        return arr[arr.length-1];
    },

    length: function(val) {
        var value = normalize(val, '');

        return value !== undefined ? value.length : 0;
    },

    list: function(val) {
        if(lib.isString(val)) {
            return val.split('');
        }
        else if(lib.isObject(val)) {
            var keys = [];

            if(Object.keys) {
                keys = Object.keys(val);
            }
            else {
                for(var k in val) {
                    keys.push(k);
                }
            }

            return lib.map(keys, function(k) {
                return { key: k,
                         value: val[k] };
            });
        }
        else if(lib.isArray(val)) {
          return val;
        }
        else {
            throw new lib.TemplateError('list filter: type not iterable');
        }
    },

    lower: function(str) {
        str = normalize(str, '');
        return str.toLowerCase();
    },

    random: function(arr) {
        return arr[Math.floor(Math.random() * arr.length)];
    },

    rejectattr: function(arr, attr) {
      return arr.filter(function (item) {
        return !item[attr];
      });
    },

    selectattr: function(arr, attr) {
      return arr.filter(function (item) {
        return !!item[attr];
      });
    },

    replace: function(str, old, new_, maxCount) {
        var originalStr = str;

        if (old instanceof RegExp) {
            return str.replace(old, new_);
        }

        if(typeof maxCount === 'undefined'){
            maxCount = -1;
        }

        var res = '';  // Output

        // Cast Numbers in the search term to string
        if(typeof old === 'number'){
            old = old + '';
        }
        else if(typeof old !== 'string') {
            // If it is something other than number or string,
            // return the original string
            return str;
        }

        // Cast numbers in the replacement to string
        if(typeof str === 'number'){
            str = str + '';
        }

        // If by now, we don't have a string, throw it back
        if(typeof str !== 'string' && !(str instanceof r.SafeString)){
            return str;
        }

        // ShortCircuits
        if(old === ''){
            // Mimic the python behaviour: empty string is replaced
            // by replacement e.g. "abc"|replace("", ".") -> .a.b.c.
            res = new_ + str.split('').join(new_) + new_;
            return r.copySafeness(str, res);
        }

        var nextIndex = str.indexOf(old);
        // if # of replacements to perform is 0, or the string to does
        // not contain the old value, return the string
        if(maxCount === 0 || nextIndex === -1){
            return str;
        }

        var pos = 0;
        var count = 0; // # of replacements made

        while(nextIndex  > -1 && (maxCount === -1 || count < maxCount)){
            // Grab the next chunk of src string and add it with the
            // replacement, to the result
            res += str.substring(pos, nextIndex) + new_;
            // Increment our pointer in the src string
            pos = nextIndex + old.length;
            count++;
            // See if there are any more replacements to be made
            nextIndex = str.indexOf(old, pos);
        }

        // We've either reached the end, or done the max # of
        // replacements, tack on any remaining string
        if(pos < str.length) {
            res += str.substring(pos);
        }

        return r.copySafeness(originalStr, res);
    },

    reverse: function(val) {
        var arr;
        if(lib.isString(val)) {
            arr = filters.list(val);
        }
        else {
            // Copy it
            arr = lib.map(val, function(v) { return v; });
        }

        arr.reverse();

        if(lib.isString(val)) {
            return r.copySafeness(val, arr.join(''));
        }
        return arr;
    },

    round: function(val, precision, method) {
        precision = precision || 0;
        var factor = Math.pow(10, precision);
        var rounder;

        if(method === 'ceil') {
            rounder = Math.ceil;
        }
        else if(method === 'floor') {
            rounder = Math.floor;
        }
        else {
            rounder = Math.round;
        }

        return rounder(val * factor) / factor;
    },

    slice: function(arr, slices, fillWith) {
        var sliceLength = Math.floor(arr.length / slices);
        var extra = arr.length % slices;
        var offset = 0;
        var res = [];

        for(var i=0; i<slices; i++) {
            var start = offset + i * sliceLength;
            if(i < extra) {
                offset++;
            }
            var end = offset + (i + 1) * sliceLength;

            var slice = arr.slice(start, end);
            if(fillWith && i >= extra) {
                slice.push(fillWith);
            }
            res.push(slice);
        }

        return res;
    },

    sort: r.makeMacro(['value', 'reverse', 'case_sensitive', 'attribute'], [], function(arr, reverse, caseSens, attr) {
         // Copy it
        arr = lib.map(arr, function(v) { return v; });

        arr.sort(function(a, b) {
            var x, y;

            if(attr) {
                x = a[attr];
                y = b[attr];
            }
            else {
                x = a;
                y = b;
            }

            if(!caseSens && lib.isString(x) && lib.isString(y)) {
                x = x.toLowerCase();
                y = y.toLowerCase();
            }

            if(x < y) {
                return reverse ? 1 : -1;
            }
            else if(x > y) {
                return reverse ? -1: 1;
            }
            else {
                return 0;
            }
        });

        return arr;
    }),

    string: function(obj) {
        return r.copySafeness(obj, obj);
    },

    striptags: function(input, preserve_linebreaks) {
        input = normalize(input, '');
        preserve_linebreaks = preserve_linebreaks || false;
        var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>|/gi;
        var trimmedInput = filters.trim(input.replace(tags, ''));
        var res = '';
        if (preserve_linebreaks) {
            res = trimmedInput
                .replace(/^ +| +$/gm, '')     // remove leading and trailing spaces
                .replace(/ +/g, ' ')          // squash adjacent spaces
                .replace(/(\r\n)/g, '\n')     // normalize linebreaks (CRLF -> LF)
                .replace(/\n\n\n+/g, '\n\n'); // squash abnormal adjacent linebreaks
        } else {
            res = trimmedInput.replace(/\s+/gi, ' ');
        }
        return r.copySafeness(input, res);
    },

    title: function(str) {
        str = normalize(str, '');
        var words = str.split(' ');
        for(var i = 0; i < words.length; i++) {
            words[i] = filters.capitalize(words[i]);
        }
        return r.copySafeness(str, words.join(' '));
    },

    trim: function(str) {
        return r.copySafeness(str, str.replace(/^\s*|\s*$/g, ''));
    },

    truncate: function(input, length, killwords, end) {
        var orig = input;
        input = normalize(input, '');
        length = length || 255;

        if (input.length <= length)
            return input;

        if (killwords) {
            input = input.substring(0, length);
        } else {
            var idx = input.lastIndexOf(' ', length);
            if(idx === -1) {
                idx = length;
            }

            input = input.substring(0, idx);
        }

        input += (end !== undefined && end !== null) ? end : '...';
        return r.copySafeness(orig, input);
    },

    upper: function(str) {
        str = normalize(str, '');
        return str.toUpperCase();
    },

    urlencode: function(obj) {
        var enc = encodeURIComponent;
        if (lib.isString(obj)) {
            return enc(obj);
        } else {
            var parts;
            if (lib.isArray(obj)) {
                parts = obj.map(function(item) {
                    return enc(item[0]) + '=' + enc(item[1]);
                });
            } else {
                parts = [];
                for (var k in obj) {
                    if (obj.hasOwnProperty(k)) {
                        parts.push(enc(k) + '=' + enc(obj[k]));
                    }
                }
            }
            return parts.join('&');
        }
    },

    urlize: function(str, length, nofollow) {
        if (isNaN(length)) length = Infinity;

        var noFollowAttr = (nofollow === true ? ' rel="nofollow"' : '');

        // For the jinja regexp, see
        // https://github.com/mitsuhiko/jinja2/blob/f15b814dcba6aa12bc74d1f7d0c881d55f7126be/jinja2/utils.py#L20-L23
        var puncRE = /^(?:\(|<|<)?(.*?)(?:\.|,|\)|\n|>)?$/;
        // from http://blog.gerv.net/2011/05/html5_email_address_regexp/
        var emailRE = /^[\w.!#$%&'*+\-\/=?\^`{|}~]+@[a-z\d\-]+(\.[a-z\d\-]+)+$/i;
        var httpHttpsRE = /^https?:\/\/.*$/;
        var wwwRE = /^www\./;
        var tldRE = /\.(?:org|net|com)(?:\:|\/|$)/;

        var words = str.split(/\s+/).filter(function(word) {
          // If the word has no length, bail. This can happen for str with
          // trailing whitespace.
          return word && word.length;
        }).map(function(word) {
          var matches = word.match(puncRE);
          var possibleUrl = matches && matches[1] || word;

          // url that starts with http or https
          if (httpHttpsRE.test(possibleUrl))
            return '' + possibleUrl.substr(0, length) + '';

          // url that starts with www.
          if (wwwRE.test(possibleUrl))
            return '' + possibleUrl.substr(0, length) + '';

          // an email address of the form username@domain.tld
          if (emailRE.test(possibleUrl))
            return '' + possibleUrl + '';

          // url that ends in .com, .org or .net that is not an email address
          if (tldRE.test(possibleUrl))
            return '' + possibleUrl.substr(0, length) + '';

          return word;

        });

        return words.join(' ');
    },

    wordcount: function(str) {
        str = normalize(str, '');
        var words = (str) ? str.match(/\w+/g) : null;
        return (words) ? words.length : null;
    },

    'float': function(val, def) {
        var res = parseFloat(val);
        return isNaN(res) ? def : res;
    },

    'int': function(val, def) {
        var res = parseInt(val, 10);
        return isNaN(res) ? def : res;
    }
};

// Aliases
filters.d = filters['default'];
filters.e = filters.escape;

module.exports = filters;
<|endoftext|>


<commit_before>//Copyright 2012 Telefonica Investigación y Desarrollo, S.A.U
//
//This file is part of RUSH.
//
//  RUSH is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
//  RUSH is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License along with RUSH
//  . If not, seehttp://www.gnu.org/licenses/.
//
//For those usages not covered by the GNU Affero General Public License please contact with::dtc_support@tid.es

var mongodb = require('mongodb');

var G = require('./my_globals').C;
var path = require('path');
var log = require('PDITCLogger');
var logger = log.newLogger();
logger.prefix = path.basename(module.filename, '.js');

function init(emitter, config) {
    'use strict';
    return function (cbAsync) {
        var callback = function (error, result) {
            cbAsync(error ? config.name+" " + String(error) : null,
                !error ? config.name + " OK" : null);
        };
        var client = new mongodb.Db(config.mongo_db,
            new mongodb.Server(config.mongo_host, config.mongo_port, {}));

        function subscribeStateCol(callback) {
            client.collection(config.collection, function (err, c) {
                if (err) {
                    logger.warning('collection', err);
                    if (callback) {
                        callback(err);
                    }
                } else {
                    var collection = c;
                    emitter.on(G.EVENT_NEWSTATE, function newEvent(data) {
                        try {
                            logger.debug('newEvent', data);
                            if (filterObj(data, config.filter)) {
                                var trimmed = trim(data, config.take);
                                collection.insert(trimmed, function (err, docs) {
                                    if (err) {
                                        logger.warning('insert', err);
                                    } else {
                                        logger.debug('insert', docs);
                                    }
                                });
                            }
                        } catch (e) {
                            logger.warning('newEvent', e);
                        }
                    });
                    if (callback) {
                        callback(null);
                    }
                }
            });
        }

        client.open(function (err, p_client) {
            if (err) {
                logger.warning('open', err);
                if (callback) {
                    callback(err);
                }
            } else {
                subscribeStateCol(function (err) {
                    callback(err);
                });
            }
        });
    };
}

exports.init = init;

function filterObj(obj, filter) {
    'use strict';

    for (var p in filter) {
        if (filter.hasOwnProperty(p)) {
            if (obj[p] === filter[p]) {
                return true;
            }
        }
    }
    return false;
}

function trim(object, propertiesHash) {
   'use strict';

    var resObj = {};

    for (var p in propertiesHash) {
        if (propertiesHash.hasOwnProperty(p)) {
            resObj[p] = extractField(object, propertiesHash[p]);
        }
    }
    return resObj;
}
function extractField(object, field) {
    'use strict';

    var arrayFields = field.split('.'), fieldValue = object;

    for(var i = 0; i < arrayFields.length; i++) {
        fieldValue = fieldValue[arrayFields[i]];
        if(fieldValue === null || fieldValue ===undefined || typeof fieldValue !== 'object') {
            return fieldValue;
        }
    }
}<commit_msg>Filter can be null<commit_after>//Copyright 2012 Telefonica Investigación y Desarrollo, S.A.U
//
//This file is part of RUSH.
//
//  RUSH is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
//  RUSH is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License along with RUSH
//  . If not, seehttp://www.gnu.org/licenses/.
//
//For those usages not covered by the GNU Affero General Public License please contact with::dtc_support@tid.es

var mongodb = require('mongodb');

var G = require('./my_globals').C;
var path = require('path');
var log = require('PDITCLogger');
var logger = log.newLogger();
logger.prefix = path.basename(module.filename, '.js');

function init(emitter, config) {
    'use strict';
    return function (cbAsync) {
        var callback = function (error, result) {
            cbAsync(error ? config.name+" " + String(error) : null,
                !error ? config.name + " OK" : null);
        };
        var client = new mongodb.Db(config.mongo_db,
            new mongodb.Server(config.mongo_host, config.mongo_port, {}));

        function subscribeStateCol(callback) {
            client.collection(config.collection, function (err, c) {
                if (err) {
                    logger.warning('collection', err);
                    if (callback) {
                        callback(err);
                    }
                } else {
                    var collection = c;
                    emitter.on(G.EVENT_NEWSTATE, function newEvent(data) {
                        try {
                            logger.debug('newEvent', data);
                            if (filterObj(data, config.filter)) {
                                var trimmed = trim(data, config.take);
                                collection.insert(trimmed, function (err, docs) {
                                    if (err) {
                                        logger.warning('insert', err);
                                    } else {
                                        logger.debug('insert', docs);
                                    }
                                });
                            }
                        } catch (e) {
                            logger.warning('newEvent', e);
                        }
                    });
                    if (callback) {
                        callback(null);
                    }
                }
            });
        }

        client.open(function (err, p_client) {
            if (err) {
                logger.warning('open', err);
                if (callback) {
                    callback(err);
                }
            } else {
                subscribeStateCol(function (err) {
                    callback(err);
                });
            }
        });
    };
}

exports.init = init;

function filterObj(obj, filter) {
    'use strict';

    if(filter === undefined || filter === null) {
        return true;
    }

    for (var p in filter) {
        if (filter.hasOwnProperty(p)) {
            if (obj[p] === filter[p]) {
                return true;
            }
        }
    }
    return false;
}

function trim(object, propertiesHash) {
   'use strict';

    var resObj = {};

    for (var p in propertiesHash) {
        if (propertiesHash.hasOwnProperty(p)) {
            resObj[p] = extractField(object, propertiesHash[p]);
        }
    }
    return resObj;
}
function extractField(object, field) {
    'use strict';

    var arrayFields = field.split('.'), fieldValue = object;

    for(var i = 0; i < arrayFields.length; i++) {
        fieldValue = fieldValue[arrayFields[i]];
        if(fieldValue === null || fieldValue ===undefined || typeof fieldValue !== 'object') {
            return fieldValue;
        }
    }
}<|endoftext|>


<commit_before>/**
 * External dependencies
 */
import classnames from 'classnames';

/**
 * WordPress dependencies
 */
import { compose } from '@wordpress/compose';
import { Button, Draggable, DropZone } from '@wordpress/components';
import { Fragment, Component } from '@wordpress/element';
import { withDispatch, withSelect } from '@wordpress/data';

/**
 * Internal dependencies
 */
import { BlockPreviewLabel } from '../';
import { __ } from '@wordpress/i18n';

/**
 * Parses drag & drop events to ensure the event contains valid transfer data.
 *
 * @param {Object} event
 * @return {Object} Parsed event data.
 */
const parseDropEvent = ( event ) => {
	let result = {
		srcClientId: null,
		srcIndex: null,
		type: null,
	};

	if ( ! event.dataTransfer ) {
		return result;
	}

	try {
		result = Object.assign( result, JSON.parse( event.dataTransfer.getData( 'text' ) ) );
	} catch ( err ) {
		return result;
	}

	return result;
};

class BlockNavigationItem extends Component {
	constructor() {
		super( ...arguments );

		this.state = {
			isDragging: false,
		};

		this.onDrop = this.onDrop.bind( this );
	}

	getInsertIndex( position ) {
		const { index } = this.props;

		if ( index !== undefined ) {
			return position.y === 'top' ? index : index + 1;
		}
	}

	onDrop( event, position ) {
		const { block: { clientId }, moveBlockToPosition, index } = this.props;
		const { srcClientId, srcIndex, type } = parseDropEvent( event );

		const isBlockDropType = ( dropType ) => dropType === 'block';
		const isSameBlock = ( src, dst ) => src === dst;

		if ( ! isBlockDropType( type ) || isSameBlock( srcClientId, clientId ) ) {
			return;
		}

		const positionIndex = this.getInsertIndex( position );
		const insertIndex = srcIndex < index ? positionIndex - 1 : positionIndex;
		moveBlockToPosition( srcClientId, insertIndex );
	}

	render() {
		const { block, index, isSelected, onClick } = this.props;
		const { clientId } = block;
		const blockElementId = `block-navigation-item-${ clientId }`;
		const transferData = {
			type: 'block',
			srcIndex: index,
			srcClientId: clientId,
		};

		return (

				<Draggable
					elementId={ blockElementId }
					transferData={ transferData }
					onDragStart={ () => this.setState( { isDragging: true } ) }
					onDragEnd={ () => this.setState( { isDragging: false } ) }
				>
					{
						( { onDraggableStart, onDraggableEnd } ) => (
							<Fragment>
								<DropZone
									className={ this.state.isDragging ? 'is-dragging-block' : undefined }
									onDrop={ this.onDrop }
								/>
								<Button
									className={ classnames(
										'components-button editor-block-navigation__item-button block-editor-block-navigation__item-button',
										{
											'is-selected': isSelected,
										}
									) }
									onClick={ onClick }
									id={ blockElementId }
									onDragStart={ onDraggableStart }
									onDragEnd={ onDraggableEnd }
									draggable
								>
									<BlockPreviewLabel
										block={ block }
										accessibilityText={ isSelected && __( '(selected block)', 'amp' ) }
									/>
								</Button>
							</Fragment>
						)
					}
				</Draggable>

		);
	}
}

const applyWithSelect = withSelect( ( select, { block: { clientId } } ) => {
	const { getBlockIndex, getBlockRootClientId } = select( 'core/block-editor' );

	return {
		index: getBlockIndex( clientId, getBlockRootClientId( clientId ) ),
	};
} );

const applyWithDispatch = withDispatch( ( dispatch, { block: { clientId } }, { select } ) => {
	const { getBlockOrder, getBlockRootClientId } = select( 'core/block-editor' );
	const { moveBlockToPosition } = dispatch( 'core/block-editor' );

	const rootClientId = getBlockRootClientId( clientId );
	const blockOrder = getBlockOrder( rootClientId );

	return {
		moveBlockToPosition: ( block, index ) => {
			// Since the BlockNavigation list is reversed, inserting at index 0 actually means inserting at the end, and vice-versa.
			const reversedIndex = blockOrder.length - 1 - index;

			moveBlockToPosition( block, rootClientId, rootClientId, reversedIndex );
		},
	};
} );

export default compose(
	applyWithSelect,
	applyWithDispatch,
)( BlockNavigationItem );
<commit_msg>Fix index calculation for drag & drop<commit_after>/**
 * External dependencies
 */
import classnames from 'classnames';

/**
 * WordPress dependencies
 */
import { compose } from '@wordpress/compose';
import { Button, Draggable, DropZone } from '@wordpress/components';
import { Fragment, Component } from '@wordpress/element';
import { withDispatch, withSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';

/**
 * Internal dependencies
 */
import { BlockPreviewLabel } from '../';
import { ALLOWED_MOVABLE_BLOCKS } from '../../constants';

/**
 * Parses drag & drop events to ensure the event contains valid transfer data.
 *
 * @param {Object} event
 * @return {Object} Parsed event data.
 */
const parseDropEvent = ( event ) => {
	let result = {
		srcClientId: null,
		srcIndex: null,
		type: null,
	};

	if ( ! event.dataTransfer ) {
		return result;
	}

	try {
		result = Object.assign( result, JSON.parse( event.dataTransfer.getData( 'text' ) ) );
	} catch ( err ) {
		return result;
	}

	return result;
};

class BlockNavigationItem extends Component {
	constructor() {
		super( ...arguments );

		this.state = {
			isDragging: false,
		};

		this.onDrop = this.onDrop.bind( this );
	}

	getInsertIndex( position ) {
		const { block: { clientId }, getBlockIndex } = this.props;

		if ( clientId !== undefined ) {
			const index = getBlockIndex( clientId );
			return position.y === 'top' ? index : index + 1;
		}
	}

	onDrop( event, position ) {
		const { block: { clientId }, moveBlockToPosition, getBlockIndex } = this.props;
		const { srcClientId, srcIndex, type } = parseDropEvent( event );

		const isBlockDropType = ( dropType ) => dropType === 'block';
		const isSameBlock = ( src, dst ) => src === dst;

		if ( ! isBlockDropType( type ) || isSameBlock( srcClientId, clientId ) ) {
			return;
		}

		const dstIndex = getBlockIndex( clientId );
		const positionIndex = this.getInsertIndex( position );
		const insertIndex = srcIndex < dstIndex ? positionIndex - 1 : positionIndex;
		moveBlockToPosition( srcClientId, insertIndex );
	}

	render() {
		const { block, getBlockIndex, isSelected, onClick } = this.props;
		const { clientId } = block;
		const blockElementId = `block-navigation-item-${ clientId }`;
		const transferData = {
			type: 'block',
			srcIndex: getBlockIndex( clientId ),
			srcClientId: clientId,
		};

		return (

				<Draggable
					elementId={ blockElementId }
					transferData={ transferData }
					onDragStart={ () => this.setState( { isDragging: true } ) }
					onDragEnd={ () => this.setState( { isDragging: false } ) }
				>
					{
						( { onDraggableStart, onDraggableEnd } ) => (
							<Fragment>
								<DropZone
									className={ this.state.isDragging ? 'is-dragging-block' : undefined }
									onDrop={ this.onDrop }
								/>
								<Button
									className={ classnames(
										'components-button editor-block-navigation__item-button block-editor-block-navigation__item-button',
										{
											'is-selected': isSelected,
										}
									) }
									onClick={ onClick }
									id={ blockElementId }
									onDragStart={ onDraggableStart }
									onDragEnd={ onDraggableEnd }
									draggable
								>
									<BlockPreviewLabel
										block={ block }
										accessibilityText={ isSelected && __( '(selected block)', 'amp' ) }
									/>
								</Button>
							</Fragment>
						)
					}
				</Draggable>

		);
	}
}

const applyWithSelect = withSelect( ( select, { block: { clientId } } ) => {
	const { getBlockOrder, getBlockRootClientId, getBlocksByClientId } = select( 'core/block-editor' );

	const blockOrder = getBlockOrder( getBlockRootClientId( clientId ) );

	// Need to reverse the list and exclude CTA blocks just like BlockNavigation does.
	const blocks = getBlocksByClientId( blockOrder ).filter( ( { name } ) => ALLOWED_MOVABLE_BLOCKS.includes( name ) ).map( ( { clientId: id } ) => id ).reverse();

	return {
		getBlockIndex: ( blockClientId ) => {
			return blocks.indexOf( blockClientId );
		},
	};
} );

const applyWithDispatch = withDispatch( ( dispatch, { block: { clientId } }, { select } ) => {
	const { getBlockOrder, getBlockRootClientId } = select( 'core/block-editor' );
	const { moveBlockToPosition } = dispatch( 'core/block-editor' );

	const rootClientId = getBlockRootClientId( clientId );
	const blockOrder = getBlockOrder( rootClientId );

	return {
		moveBlockToPosition: ( block, index ) => {
			// Since the BlockNavigation list is reversed, inserting at index 0 actually means inserting at the end, and vice-versa.
			const reversedIndex = blockOrder.length - 1 - index;

			moveBlockToPosition( block, rootClientId, rootClientId, reversedIndex );
		},
	};
} );

export default compose(
	applyWithSelect,
	applyWithDispatch,
)( BlockNavigationItem );
<|endoftext|>


<commit_before>/**
 * WordPress dependencies
 */
import { __ } from '@wordpress/i18n';
import { IconButton } from '@wordpress/components';
import { Component, Fragment } from '@wordpress/element';
import { withDispatch, withSelect } from '@wordpress/data';
import { compose } from '@wordpress/compose';

/**
 * Internal dependencies
 */
import Indicator from './indicator';
import { Reorderer } from '../';
import { STORY_PAGE_INNER_WIDTH } from './../../constants';
import './edit.css';

// This is the average of left (20px) and right (30px) margin.
const PAGE_MARGIN = 25;

class EditorCarousel extends Component {
	constructor() {
		super( ...arguments );

		this.translateWrapper.bind( this );
	}

	translateWrapper() {
		const wrapper = document.querySelector( '.editor-writing-flow .editor-block-list__layout' );

		if ( ! wrapper ) {
			return;
		}

		if ( this.props.isReordering ) {
			wrapper.style.display = 'none';
		} else {
			wrapper.style.display = '';
			wrapper.style.transform = `translateX(calc(50% - ${ STORY_PAGE_INNER_WIDTH / 2 }px - ${ ( this.props.currentIndex ) * PAGE_MARGIN * 2 }px - ${ this.props.currentIndex * STORY_PAGE_INNER_WIDTH }px))`;
		}
	}

	componentDidMount() {
		this.translateWrapper();
	}

	componentDidUpdate() {
		this.translateWrapper();
	}

	render() {
		const { pages, currentPage, previousPage, nextPage, onChangePage, isReordering } = this.props;

		const goToPage = ( page ) => {
			onChangePage( page );
		};

		if ( isReordering ) {
			return <Reorderer />;
		}

		return (
			<Fragment>

					<IconButton
						icon="arrow-left-alt2"
						label={ __( 'Previous Page', 'amp' ) }
						onClick={ ( e ) => {
							e.preventDefault();
							goToPage( previousPage );
						} }
						disabled={ null === previousPage }
					/>
					<Indicator
						pages={ pages }
						currentPage={ currentPage }
						onClick={ goToPage }
					/>
					<IconButton
						icon="arrow-right-alt2"
						label={ __( 'Next Page', 'amp' ) }
						onClick={ ( e ) => {
							e.preventDefault();
							goToPage( nextPage );
						} }
						disabled={ null === nextPage }
					/>

			</Fragment>
		);
	}
}

export default compose(
	withSelect( ( select ) => {
		const {
			getBlockOrder,
			getBlocksByClientId,
			getAdjacentBlockClientId,
		} = select( 'core/block-editor' );
		const { getCurrentPage, isReordering } = select( 'amp/story' );

		const currentPage = getCurrentPage();
		const pages = getBlocksByClientId( getBlockOrder() );

		return {
			pages,
			currentPage,
			currentIndex: pages.findIndex( ( { clientId } ) => clientId === currentPage ),
			previousPage: getCurrentPage() ? getAdjacentBlockClientId( currentPage, -1 ) : null,
			nextPage: getCurrentPage() ? getAdjacentBlockClientId( currentPage, 1 ) : null,
			isReordering: isReordering(),
		};
	} ),
	withDispatch( ( dispatch ) => {
		const { setCurrentPage } = dispatch( 'amp/story' );
		const { selectBlock } = dispatch( 'core/block-editor' );

		return {
			onChangePage: ( pageClientId ) => {
				setCurrentPage( pageClientId );
				selectBlock( pageClientId );
			},
		};
	} )
)( EditorCarousel );
<commit_msg>Consider page margin in tranform.<commit_after>/**
 * WordPress dependencies
 */
import { __ } from '@wordpress/i18n';
import { IconButton } from '@wordpress/components';
import { Component, Fragment } from '@wordpress/element';
import { withDispatch, withSelect } from '@wordpress/data';
import { compose } from '@wordpress/compose';

/**
 * Internal dependencies
 */
import Indicator from './indicator';
import { Reorderer } from '../';
import { STORY_PAGE_INNER_WIDTH } from './../../constants';
import './edit.css';

// This is the average of left (20px) and right (30px) margin.
const PAGE_MARGIN = 25;

class EditorCarousel extends Component {
	constructor() {
		super( ...arguments );

		this.translateWrapper.bind( this );
	}

	translateWrapper() {
		const wrapper = document.querySelector( '.editor-writing-flow .editor-block-list__layout' );

		if ( ! wrapper ) {
			return;
		}

		if ( this.props.isReordering ) {
			wrapper.style.display = 'none';
		} else {
			wrapper.style.display = '';
			wrapper.style.transform = `translateX(calc(50% - ${ ( STORY_PAGE_INNER_WIDTH + PAGE_MARGIN * 2 ) / 2 }px - ${ ( this.props.currentIndex ) * PAGE_MARGIN * 2 }px - ${ this.props.currentIndex * STORY_PAGE_INNER_WIDTH }px))`;
		}
	}

	componentDidMount() {
		this.translateWrapper();
	}

	componentDidUpdate() {
		this.translateWrapper();
	}

	render() {
		const { pages, currentPage, previousPage, nextPage, onChangePage, isReordering } = this.props;

		const goToPage = ( page ) => {
			onChangePage( page );
		};

		if ( isReordering ) {
			return <Reorderer />;
		}

		return (
			<Fragment>

					<IconButton
						icon="arrow-left-alt2"
						label={ __( 'Previous Page', 'amp' ) }
						onClick={ ( e ) => {
							e.preventDefault();
							goToPage( previousPage );
						} }
						disabled={ null === previousPage }
					/>
					<Indicator
						pages={ pages }
						currentPage={ currentPage }
						onClick={ goToPage }
					/>
					<IconButton
						icon="arrow-right-alt2"
						label={ __( 'Next Page', 'amp' ) }
						onClick={ ( e ) => {
							e.preventDefault();
							goToPage( nextPage );
						} }
						disabled={ null === nextPage }
					/>

			</Fragment>
		);
	}
}

export default compose(
	withSelect( ( select ) => {
		const {
			getBlockOrder,
			getBlocksByClientId,
			getAdjacentBlockClientId,
		} = select( 'core/block-editor' );
		const { getCurrentPage, isReordering } = select( 'amp/story' );

		const currentPage = getCurrentPage();
		const pages = getBlocksByClientId( getBlockOrder() );

		return {
			pages,
			currentPage,
			currentIndex: pages.findIndex( ( { clientId } ) => clientId === currentPage ),
			previousPage: getCurrentPage() ? getAdjacentBlockClientId( currentPage, -1 ) : null,
			nextPage: getCurrentPage() ? getAdjacentBlockClientId( currentPage, 1 ) : null,
			isReordering: isReordering(),
		};
	} ),
	withDispatch( ( dispatch ) => {
		const { setCurrentPage } = dispatch( 'amp/story' );
		const { selectBlock } = dispatch( 'core/block-editor' );

		return {
			onChangePage: ( pageClientId ) => {
				setCurrentPage( pageClientId );
				selectBlock( pageClientId );
			},
		};
	} )
)( EditorCarousel );
<|endoftext|>


<commit_before>
    // ------------- Multibase Odometer ---------------
    var value = 0;
    base = 10;
    var odometer = "00";

    //Sets the base from drop-down
    function setBase(n) {
      if (n == 0) {
	 document.getElementById("basediv").style.visibility="visible";
	 var val = document.getElementById("baseinput").value;
	 if (val > 32) {
	    alert("Sorry, I can only handle bases up to 32.");
    //        document.getElementById("basediv").style.visibility="hidden";
	    document.getElementById("baseinput").value = base;
	    return;    // ignore bases above 32
	 }
	 base = val;
	 value = 0;
	 document.getElementById("odometer").innerHTML = "00";
	 document.getElementById("decimal").innerHTML = value;
	 setOdoLabel(base);
	 return;
      }
    }

    function setOdoLabel(base) {
       var label = document.getElementById("odolabel")
       if (base == 2)
	 label.innerHTML = "binary";
       else if (base == 8)
	 label.innerHTML = "octal";
       else if (base == 10)
	 label.innerHTML = "decimal";
       else if (base == 16)
	 label.innerHTML = "hex";
       else
	 label.innerHTML = "base " + base;
    }

    // Advance the odometer
    function advance() {
       value += 1;
       if (value > limit(base)) {
	 value = 0;
       }
       odometer =  padForBase(decToAltBase(value, base), base);
       document.getElementById("odometer").innerHTML = odometer;
       document.getElementById("decimal").innerHTML = value;
    }
<commit_msg>Deleting multiodometer script; in html.<commit_after><|endoftext|>


<commit_before>OAuth2.adapter('viame', {
  /**
   * @return {URL} URL to the page that returns the authorization code
   */
  authorizationCodeURL: function(config) {
    return ('https://api.via.me/oauth/authorize/?' +
      'client_id={{CLIENT_ID}}&' +
      'redirect_uri={{REDIRECT_URI}}&' +
      'response_type=code')
        .replace('{{CLIENT_ID}}', config.clientId)
        .replace('{{REDIRECT_URI}}', this.redirectURL(config));
  },

  /**
   * @return {URL} URL to the page that we use to inject the content
   * script into
   */
  redirectURL: function(config) {
    return 'http://radiumone.com/robots.txt';
  },

  /**
   * @return {String} Authorization code for fetching the access token
   */
  parseAuthorizationCode: function(url) {
    var error = url.match(/[&\?]error=([^&]+)/);
    if (error) {
      throw 'Error getting authorization code: ' + error[1];
    }
    return url.match(/[&\?]code=([\w\/\-]+)/)[1];
  },

  /**
   * @return {URL} URL to the access token providing endpoint
   */
  accessTokenURL: function() {
    return 'http://via.me/oauth/access_token';
  },

  /**
   * @return {String} HTTP method to use to get access tokens
   */
  accessTokenMethod: function() {
    return 'POST';
  },

  /**
   * @return {Object} The payload to use when getting the access token
   */
  accessTokenParams: function(authorizationCode, config) {
    return {
      code: authorizationCode,
      client_id: config.clientId,
      client_secret: config.clientSecret,
      redirect_uri: this.redirectURL(config),
      grant_type: 'authorization_code',
      response_type: 'token'
    };
  },

  /**
   * @return {Object} Object containing accessToken {String},
   * refreshToken {String} and expiresIn {Int}
   */
  parseAccessToken: function(response) {
    var parsedResponse = JSON.parse(response);
    return {
      accessToken: parsedResponse.access_token,
      expiresIn: Number.MAX_VALUE
    };
  }
});
<commit_msg>via.me only sends back access token<commit_after>OAuth2.adapter('viame', {
  /**
   * @return {URL} URL to the page that returns the authorization code
   */
  authorizationCodeURL: function(config) {
    return ('https://api.via.me/oauth/authorize/?' +
      'client_id={{CLIENT_ID}}&' +
      'redirect_uri={{REDIRECT_URI}}&' +
      'response_type=code')
        .replace('{{CLIENT_ID}}', config.clientId)
        .replace('{{REDIRECT_URI}}', this.redirectURL(config));
  },

  /**
   * @return {URL} URL to the page that we use to inject the content
   * script into
   */
  redirectURL: function(config) {
    return 'http://radiumone.com/robots.txt';
  },

  /**
   * @return {String} Authorization code for fetching the access token
   */
  parseAuthorizationCode: function(url) {
    var error = url.match(/[&\?]error=([^&]+)/);
    if (error) {
      throw 'Error getting authorization code: ' + error[1];
    }
    return url.match(/[&\?]code=([\w\/\-]+)/)[1];
  },

  /**
   * @return {URL} URL to the access token providing endpoint
   */
  accessTokenURL: function() {
    return 'http://via.me/oauth/access_token';
  },

  /**
   * @return {String} HTTP method to use to get access tokens
   */
  accessTokenMethod: function() {
    return 'POST';
  },

  /**
   * @return {Object} The payload to use when getting the access token
   */
  accessTokenParams: function(authorizationCode, config) {
    return {
      code: authorizationCode,
      client_id: config.clientId,
      client_secret: config.clientSecret,
      redirect_uri: this.redirectURL(config),
      grant_type: 'authorization_code',
      response_type: 'token'
    };
  },

  /**
   * @return {Object} Object containing accessToken {String},
   * refreshToken {String} and expiresIn {Int}
   */
  parseAccessToken: function(response) {
    var parsedResponse = JSON.parse(response);
    return {
      accessToken: parsedResponse.access_token
    };
  }
});
<|endoftext|>


<commit_before>/*
Class: ResponsiveMenu
Menu widget to convert menu into a slide down menu when screen size reaches certain breakpoint.
*/
/* global __ */
__.classes.ResponsiveMenu = __.core.Classes.create({
	init: function(){
		var _this = this;
		this.__base(arguments);
		if(typeof this.$action === 'string'){
			this.$action = this.$.find(this.$action);
		}
		if(typeof this.$list === 'string'){
			this.$list = this.$.find(this.$list);
		}
		if(!this.responsiveHandler){
			this.responsiveHandler = new __.classes.ResponsiveHandler();
		}
		if(!this.responsiveSubscription){
			this.responsiveSubscription = this.responsiveHandler.sub('change', function(_data){
				_this.switchBreakpoint(_data.breakPoint);
			});
		}

		//--set to initial breakpoint
		this.switchBreakpoint(this.responsiveHandler.getBreakPoint());

		//--attach action listener
		this.$action.on('click', function(){
			_this.toggleList();
		});
	}
	,properties: {
		$: null
		,$action: '.siteMainNavTitle'
		,$list: '.siteMainNavList'
		,closedClass: 'hasClosedMenu'
		,openedClass: 'hasOpenMenu'
		,nvpBreakPoints: 'nvp'
		,responsiveHandler: null
		,responsiveSubscription: null
		,showList: function(){
			return this.toggleList('show');
		}
		,hideList: function(){
			return this.toggleList('hide');
		}
		,toggleList: function(_action){
			var _this = this;
			var _isStartingVisible, _method;
			switch(_action){
				case 'show':
					_isStartingVisible = false;
					_method = 'slideDown';
				break;
				case 'hide':
					_isStartingVisible = true;
					_method = 'slideUp';
				break;
				default:
					_isStartingVisible = _this.$list.is(':visible');
					_method = 'slideToggle';
				break;
			}
			if(!_isStartingVisible){
				_this.$.addClass(_this.openedClass).removeClass(_this.closedClass);
			}
			_this.$list[_method](function(){
				if(_isStartingVisible){
					_this.$.removeClass(_this.openedClass).addClass(_this.closedClass);
				}
			});
			return this;
		}
		,state: null
		,switchBreakpoint: function(_breakpoint){
			if(_breakpoint !== this.state){
				if(_breakpoint === this.nvpBreakPoints){
					this.switchToNVP();
				}else{
					this.switchToWVP();
					// __.topnavigationDropdownhandler.sizeAndCenter2();
				}
				this.state = _breakpoint;
			}
		}
		,switchToNVP: function(){
			//--show action
			this.$action.show();
			//--hide menu
			this.$list.hide();
		}
		,switchToWVP: function(){
			//--hide action
			this.$action.hide();
			//--show menu
			this.$list.show();
		}
	}
});

<commit_msg>ui/responsiveMenu: move opening and closing of menu out into methods so they can be overridden or called directly<commit_after>/*
Class: ResponsiveMenu
Menu widget to convert menu into a slide down menu when screen size reaches certain breakpoint.
*/
/* global __ */
__.classes.ResponsiveMenu = __.core.Classes.create({
	init: function(){
		var _this = this;
		this.__base(arguments);
		if(typeof this.$action === 'string'){
			this.$action = this.$.find(this.$action);
		}
		if(typeof this.$list === 'string'){
			this.$list = this.$.find(this.$list);
		}
		if(!this.responsiveHandler){
			this.responsiveHandler = new __.classes.ResponsiveHandler();
		}
		if(!this.responsiveSubscription){
			this.responsiveSubscription = this.responsiveHandler.sub('change', function(_data){
				_this.switchBreakpoint(_data.breakPoint);
			});
		}

		//--set to initial breakpoint
		this.switchBreakpoint(this.responsiveHandler.getBreakPoint());

		//--attach action listener
		this.$action.on('click', function(){
			_this.toggleOpen();
		});
	}
	,properties: {
		$: null
		,$action: '.siteMainNavTitle'
		,$list: '.siteMainNavList'
		,closedClass: 'hasClosedMenu'
		,openedClass: 'hasOpenMenu'
		,nvpBreakPoints: 'nvp'
		,responsiveHandler: null
		,responsiveSubscription: null
		,state: null
		,switchBreakpoint: function(_breakpoint){
			if(_breakpoint !== this.state){
				if(_breakpoint === this.nvpBreakPoints){
					this.switchToNVP();
				}else{
					this.switchToWVP();
					// __.topnavigationDropdownhandler.sizeAndCenter2();
				}
				this.state = _breakpoint;
			}
		}
		,switchToNVP: function(){
			//--show action
			this.$action.show();
			//--hide menu
			this.$list.hide();

			this.isOpened = false;
		}
		,switchToWVP: function(){
			//--hide action
			this.$action.show().css('display', '');
			//--show menu
			this.$list.show().css('display', '');

			this.isOpened = undefined;
		}
		,closeList: function(){
			if(this.isOpened){
				var _this = this;
				this.$list.slideUp(function(){
					_this.$.removeClass(_this.openedClass).addClass(_this.closedClass);
					_this.isOpened = false;
				});
			}
		}
		,openList: function(){
			if(!this.isOpened){
				this.$.addClass(this.openedClass).removeClass(this.closedClass);
				this.$list.slideDown();
				this.isOpened = true;
			}
		}
		,isOpened: undefined
		,toggleOpen: function(){
			if(typeof this.isOpened === 'undefined'){
				this.isOpened = this.$list.is(':visible');
			}
			if(this.isOpened){
				this.closeList();
			}else{
				this.openList();
			}
		}
	}
});
<|endoftext|>


<commit_before>var slack = require('node-slack');
var mqtt = require('mqtt');
var config = require('config');
var dgram = require('dgram');
var fs = require('fs-extra');
var dict = require('dict');
var gitHubApi = require('@octokit/rest');
var winston = require('winston');

// Set up default log format for Winston logger
var logger = new(winston.Logger)({
    transports: [
        new(winston.transports.Console)({
            'timestamp': true,
            'colorize': true
        })
    ]
});

// GitHub access
var github = new gitHubApi({
    debug: false,
    headers: {
        'user-agent': 'Butler-Sense-App' // GitHub is happy with a unique user agent
    },
    timeout: 5000
});
// protocol: "https",
// host: config.get('Butler.gitHub.host'),
// pathPrefix: config.get('Butler.gitHub.pathPrefix'),
// Promise: require('bluebird'),
// followRedirects: false, // default: true; there's currently an issue with non-get redirects, so allow ability to disable follow-redirects

// Load our own libs
var qrsUtil = require('./qrsUtil');

// Helper function to read the contents of the certificate files:
// const readCert = filename => fs.readFileSync(path.resolve(__dirname, certificatesPath, filename));
const readCert = filename => fs.readFileSync(filename);

//  Engine config
var configEngine = {
    engineVersion: config.get('Butler.configEngine.engineVersion'),
    host: config.get('Butler.configEngine.server'),
    port: config.get('Butler.configEngine.serverPort'),
    isSecure: config.get('Butler.configEngine.isSecure'),
    headers: config.get('Butler.configEngine.headers'),
    cert: readCert(config.get('Butler.configEngine.cert')),
    key: readCert(config.get('Butler.configEngine.key')),
    rejectUnauthorized: config.get('Butler.configEngine.rejectUnauthorized')
};

// QRS config
const configQRS = {
    authentication: config.get('Butler.configQRS.authentication'),
    host: config.get('Butler.configQRS.host'),
    port: config.get('Butler.configQRS.port'),
    useSSL: config.get('Butler.configQRS.useSSL'),
    headerKey: config.get('Butler.configQRS.headerKey'),
    headerValue: config.get('Butler.configQRS.headerValue'),
    cert: readCert(config.get('Butler.configQRS.cert')),
    key: readCert(config.get('Butler.configQRS.key')),
    ca: readCert(config.get('Butler.configQRS.ca'))
};

// ------------------------------------
// Slack config
var slackWebhookURL = config.get('Butler.slackConfig.webhookURL');
var slackLoginNotificationChannel = config.get('Butler.slackConfig.loginNotificationChannel');
var slackTaskFailureChannel = config.get('Butler.slackConfig.taskFailureChannel');

// Create Slack object
var slackObj = new slack(slackWebhookURL);

// ------------------------------------
// Data structures needed to keep track of currently active users/sessions
var currentUsers = dict();
var currentUsersPerServer = dict();

// ------------------------------------
// Create MQTT client object and connect to MQTT broker
var mqttClient = mqtt.connect('mqtt://' + config.get('Butler.mqttConfig.brokerIP'));
/*
Following might be needed for conecting to older Mosquitto versions
var mqttClient  = mqtt.connect('mqtt://<IP of MQTT server>', {
  protocolId: 'MQIsdp',
  protocolVersion: 3
});
*/

// ------------------------------------
// UDP server connection parameters
var udp_host = config.get('Butler.udpServerConfig.serverIP');

// Prepare to listen on port X for incoming UDP connections regarding session starting/stoping, or connection opening/closing
var udpServerSessionConnectionSocket = dgram.createSocket({
    type: 'udp4',
    reuseAddr: true
});
var udp_port_session_connection = config.get('Butler.udpServerConfig.portSessionConnectionEvents');

// Prepare to listen on port Y for incoming UDP connections regarding failed tasks
var udpServerTaskFailureSocket = dgram.createSocket({
    type: 'udp4',
    reuseAddr: true
});
var udp_port_take_failure = config.get('Butler.udpServerConfig.portTaskFailure');

// ------------------------------------
// Folder under which QVD folders are to be created
var qvdFolder = config.get('Butler.qvdPath');

module.exports = {
    config,
    qrsUtil,
    configEngine,
    configQRS,
    slack,
    slackLoginNotificationChannel,
    slackTaskFailureChannel,
    currentUsers,
    currentUsersPerServer,
    udpServerSessionConnectionSocket,
    udpServerTaskFailureSocket,
    udp_host,
    udp_port_session_connection,
    udp_port_take_failure,
    mqttClient,
    qvdFolder,
    github,
    logger
};
<commit_msg>Fix posting to Slack<commit_after>var slack = require('node-slack');
var mqtt = require('mqtt');
var config = require('config');
var dgram = require('dgram');
var fs = require('fs-extra');
var dict = require('dict');
var gitHubApi = require('@octokit/rest');
var winston = require('winston');

// Set up default log format for Winston logger
var logger = new(winston.Logger)({
    transports: [
        new(winston.transports.Console)({
            'timestamp': true,
            'colorize': true
        })
    ]
});

// GitHub access
var github = new gitHubApi({
    debug: false,
    headers: {
        'user-agent': 'Butler-Sense-App' // GitHub is happy with a unique user agent
    },
    timeout: 5000
});
// protocol: "https",
// host: config.get('Butler.gitHub.host'),
// pathPrefix: config.get('Butler.gitHub.pathPrefix'),
// Promise: require('bluebird'),
// followRedirects: false, // default: true; there's currently an issue with non-get redirects, so allow ability to disable follow-redirects

// Load our own libs
var qrsUtil = require('./qrsUtil');

// Helper function to read the contents of the certificate files:
// const readCert = filename => fs.readFileSync(path.resolve(__dirname, certificatesPath, filename));
const readCert = filename => fs.readFileSync(filename);

//  Engine config
var configEngine = {
    engineVersion: config.get('Butler.configEngine.engineVersion'),
    host: config.get('Butler.configEngine.server'),
    port: config.get('Butler.configEngine.serverPort'),
    isSecure: config.get('Butler.configEngine.isSecure'),
    headers: config.get('Butler.configEngine.headers'),
    cert: readCert(config.get('Butler.configEngine.cert')),
    key: readCert(config.get('Butler.configEngine.key')),
    rejectUnauthorized: config.get('Butler.configEngine.rejectUnauthorized')
};

// QRS config
const configQRS = {
    authentication: config.get('Butler.configQRS.authentication'),
    host: config.get('Butler.configQRS.host'),
    port: config.get('Butler.configQRS.port'),
    useSSL: config.get('Butler.configQRS.useSSL'),
    headerKey: config.get('Butler.configQRS.headerKey'),
    headerValue: config.get('Butler.configQRS.headerValue'),
    cert: readCert(config.get('Butler.configQRS.cert')),
    key: readCert(config.get('Butler.configQRS.key')),
    ca: readCert(config.get('Butler.configQRS.ca'))
};

// ------------------------------------
// Slack config
var slackWebhookURL = config.get('Butler.slackConfig.webhookURL');
var slackLoginNotificationChannel = config.get('Butler.slackConfig.loginNotificationChannel');
var slackTaskFailureChannel = config.get('Butler.slackConfig.taskFailureChannel');

// Create Slack object
var slackObj = new slack(slackWebhookURL);

// ------------------------------------
// Data structures needed to keep track of currently active users/sessions
var currentUsers = dict();
var currentUsersPerServer = dict();

// ------------------------------------
// Create MQTT client object and connect to MQTT broker
var mqttClient = mqtt.connect('mqtt://' + config.get('Butler.mqttConfig.brokerIP'));
/*
Following might be needed for conecting to older Mosquitto versions
var mqttClient  = mqtt.connect('mqtt://<IP of MQTT server>', {
  protocolId: 'MQIsdp',
  protocolVersion: 3
});
*/

// ------------------------------------
// UDP server connection parameters
var udp_host = config.get('Butler.udpServerConfig.serverIP');

// Prepare to listen on port X for incoming UDP connections regarding session starting/stoping, or connection opening/closing
var udpServerSessionConnectionSocket = dgram.createSocket({
    type: 'udp4',
    reuseAddr: true
});
var udp_port_session_connection = config.get('Butler.udpServerConfig.portSessionConnectionEvents');

// Prepare to listen on port Y for incoming UDP connections regarding failed tasks
var udpServerTaskFailureSocket = dgram.createSocket({
    type: 'udp4',
    reuseAddr: true
});
var udp_port_take_failure = config.get('Butler.udpServerConfig.portTaskFailure');

// ------------------------------------
// Folder under which QVD folders are to be created
var qvdFolder = config.get('Butler.qvdPath');

module.exports = {
    config,
    qrsUtil,
    configEngine,
    configQRS,
    slackObj,
    slackLoginNotificationChannel,
    slackTaskFailureChannel,
    currentUsers,
    currentUsersPerServer,
    udpServerSessionConnectionSocket,
    udpServerTaskFailureSocket,
    udp_host,
    udp_port_session_connection,
    udp_port_take_failure,
    mqttClient,
    qvdFolder,
    github,
    logger
};
<|endoftext|>


<commit_before>import * as LogManager from 'aurelia-logging';
import {Loader} from 'aurelia-loader';
import {relativeToFile} from 'aurelia-path';
import {ViewCompiler} from './view-compiler';
import {ResourceRegistry, ViewResources} from './resource-registry';

var importSplitter = /\s*,\s*/,
    logger = LogManager.getLogger('templating');

export class ViewEngine {
  static inject() { return [Loader, ViewCompiler, ResourceRegistry]; }
	constructor(loader, viewCompiler, appResources){
		this.loader = loader;
		this.viewCompiler = viewCompiler;
    this.appResources = appResources;
    this.importedViews = {};
	}

	loadViewFactory(url, compileOptions, associatedModuleId){
    var existing = this.importedViews[url];
    if(existing){
      return Promise.resolve(existing);
    }

    return this.loader.loadTemplate(url).then(template => {
      return this.loadTemplateResources(url, template, associatedModuleId).then(resources => {
        existing = this.importedViews[url];
        if(existing){
          return existing;
        }

        var viewFactory = this.viewCompiler.compile(template, resources, compileOptions);
        this.importedViews[url] = viewFactory;
        return viewFactory;
      });
    });
  }

  loadTemplateResources(templateUrl, template, associatedModuleId){
    var importIds, names, i, ii, src, current,
        registry = new ViewResources(this.appResources, templateUrl),
        dxImportElements = template.content.querySelectorAll('import'),
        associatedModule;

    if(dxImportElements.length === 0 && !associatedModuleId){
      return Promise.resolve(registry);
    }

    importIds = new Array(dxImportElements.length);
    names = new Array(dxImportElements.length);

    for(i = 0, ii = dxImportElements.length; i < ii; ++i){
      current = dxImportElements[i];
      src = current.getAttribute('from');

      if(!src){
        throw new Error(`Import element in ${templateUrl} has no "from" attribute.`);
      }

      importIds[i] = src;
      names[i] = current.getAttribute('as');
    }

    importIds = importIds.map(x => relativeToFile(x, templateUrl));
    logger.debug(`importing resources for ${templateUrl}`, importIds);

    return this.resourceCoordinator.importResourcesFromModuleIds(importIds).then(toRegister => {
      for(i = 0, ii = toRegister.length; i < ii; ++i){
        toRegister[i].register(registry, names[i]);
      }

      if(associatedModuleId){
        associatedModule = this.resourceCoordinator.getExistingModuleAnalysis(associatedModuleId);

        if(associatedModule){
          associatedModule.register(registry);
        }
      }

      return registry;
    });
  }
}<commit_msg>fix(view-engine): remove module elements from templates<commit_after>import * as LogManager from 'aurelia-logging';
import {Loader} from 'aurelia-loader';
import {relativeToFile} from 'aurelia-path';
import {ViewCompiler} from './view-compiler';
import {ResourceRegistry, ViewResources} from './resource-registry';

var importSplitter = /\s*,\s*/,
    logger = LogManager.getLogger('templating');

export class ViewEngine {
  static inject() { return [Loader, ViewCompiler, ResourceRegistry]; }
	constructor(loader, viewCompiler, appResources){
		this.loader = loader;
		this.viewCompiler = viewCompiler;
    this.appResources = appResources;
    this.importedViews = {};
	}

	loadViewFactory(url, compileOptions, associatedModuleId){
    var existing = this.importedViews[url];
    if(existing){
      return Promise.resolve(existing);
    }

    return this.loader.loadTemplate(url).then(template => {
      return this.loadTemplateResources(url, template, associatedModuleId).then(resources => {
        existing = this.importedViews[url];
        if(existing){
          return existing;
        }

        var viewFactory = this.viewCompiler.compile(template, resources, compileOptions);
        this.importedViews[url] = viewFactory;
        return viewFactory;
      });
    });
  }

  loadTemplateResources(templateUrl, template, associatedModuleId){
    var importIds, names, i, ii, src, current,
        registry = new ViewResources(this.appResources, templateUrl),
        dxImportElements = template.content.querySelectorAll('import'),
        associatedModule;

    if(dxImportElements.length === 0 && !associatedModuleId){
      return Promise.resolve(registry);
    }

    importIds = new Array(dxImportElements.length);
    names = new Array(dxImportElements.length);

    for(i = 0, ii = dxImportElements.length; i < ii; ++i){
      current = dxImportElements[i];
      src = current.getAttribute('from');

      if(!src){
        throw new Error(`Import element in ${templateUrl} has no "from" attribute.`);
      }

      importIds[i] = src;
      names[i] = current.getAttribute('as');

      if(current.parentNode){
        current.parentNode.removeChild(current);
      }
    }

    importIds = importIds.map(x => relativeToFile(x, templateUrl));
    logger.debug(`importing resources for ${templateUrl}`, importIds);

    return this.resourceCoordinator.importResourcesFromModuleIds(importIds).then(toRegister => {
      for(i = 0, ii = toRegister.length; i < ii; ++i){
        toRegister[i].register(registry, names[i]);
      }

      if(associatedModuleId){
        associatedModule = this.resourceCoordinator.getExistingModuleAnalysis(associatedModuleId);

        if(associatedModule){
          associatedModule.register(registry);
        }
      }

      return registry;
    });
  }
}<|endoftext|>


<commit_before>'use strict'

// import material components
import {
  View,
  Component,
  Container,
  Checkbox,
  Button,
  Text
} from 'material'

import Layout from 'material/src/layout'
import css from 'material/src/module/css'

import iconStar from '../icon/star.svg'
import iconAccessibility from '../icon/accessibility.svg'
import iconPhone from '../icon/phone.svg'
import iconHappy from '../icon/happy.svg'
import iconLink from '../icon/link.svg'

/**
 * [initTest description]
 * @return {[type]} [description]
 */
export default function (body) {
  var layout = new Layout([Container, 'button', {},
    [Container, 'hero', {},
      [Button, 'first', { text: 'Flat' }],
      [Button, 'second', { text: 'Raised', type: 'raised', color: 'primary' }],
      [Button, 'third', { icon: iconStar, type: 'action' }],
      [Button, 'fourth', { icon: iconStar, text: 'text' }],
      [Button, 'fifth', { icon: iconStar, type: 'floating', color: 'secondary' }]
    ],
    [Container, 'containerbutton', {},
      [Container, 'options', {},
        [Checkbox, 'darktheme', { name: 'darktheme', label: 'Dark Theme' }]
      ],
      [Container, 'button-default', {},
        [Text, 'standard-button', { text: 'Standard Button', type: 'subheading2' }],
        [Container, 'buttons-container', {},
          [Button, 'default', { text: 'default' }],
          [Button, 'default-icontext', { icon: iconHappy, text: 'icon text' }],
          [Button, 'default-compact', { text: 'Compact', style: 'compact' }],
          [Button, 'default-dense', { text: 'Dense', style: 'dense' }],
          [Button, 'default-densecompact', { text: 'Compact dense', style: 'compact dense' }],
          [Button, 'default-link', { text: 'Link', tag: 'a' }]
        ],
        [Container, 'buttons-container', {},
          [Button, 'default', { text: 'default', color: 'primary' }],
          [Button, 'default-icontext', { icon: iconHappy, text: 'icon text', color: 'primary' }],
          [Button, 'default-compact', { text: 'Compact', style: 'compact', color: 'primary' }],
          [Button, 'default-dense', { text: 'Dense', style: 'dense', color: 'primary' }],
          [Button, 'default-densecompact', { text: 'Compact dense', style: 'compact dense', color: 'primary' }],
          [Button, 'default-link', { text: 'Link', color: 'primary', tag: 'a' }]
        ],
        [Container, 'buttons-container', {},
          [Button, 'default', { text: 'default', color: 'secondary' }],
          [Button, 'default-icontext', { icon: iconHappy, text: 'icon text', color: 'secondary' }],
          [Button, 'default-compact', { text: 'Compact', style: 'compact', color: 'secondary' }],
          [Button, 'default-dense', { text: 'Dense', style: 'dense', color: 'secondary' }],
          [Button, 'default-densecompact', { text: 'Compact dense', style: 'compact dense', color: 'secondary' }],
          [Button, 'default-link', { text: 'Link', color: 'secondary', tag: 'a' }]
        ],
        [Text, 'raised-button', { text: 'Raised Button', type: 'subheading2' }],
        [Container, 'buttons-raised', {},
          [Button, 'raised', { text: 'raised', type: 'raised' }],
          [Button, 'default-icontext', { icon: iconHappy, type: 'raised', text: 'icon text' }],
          [Button, 'raised-compact', { text: 'Compact', type: 'raised', style: 'compact' }],
          [Button, 'raised-dense', { text: 'Dense', type: 'raised', style: 'dense' }],
          [Button, 'raised-densecompact', { text: 'Compact dense', type: 'raised', style: 'compact dense' }],
          [Button, 'raised-link', { text: 'Link', type: 'raised' }],
          [Button, 'raised-link', { icon: iconStar, type: 'raised' }]
        ],
        [Container, 'buttons-raised-primary', {},
          [Button, 'raised', { text: 'raised primary', type: 'raised', color: 'primary' }],
          [Button, 'default-icontext', { icon: iconHappy, type: 'raised', text: 'icon text', color: 'primary' }],
          [Button, 'raised-compact', { text: 'Compact', type: 'raised', style: 'compact', color: 'primary' }],
          [Button, 'raised-dense', { text: 'Dense', style: 'dense', type: 'raised', color: 'primary' }],
          [Button, 'raised-densecompact', { text: 'Compact dense', style: 'dense compact', type: 'raised', color: 'primary' }],
          [Button, 'raised-link', { text: 'Link', type: 'raised', color: 'primary' }],
          [Button, 'raised-link', { icon: iconStar, type: 'raised', color: 'primary' }]
        ],
        [Container, 'buttons-raised-secondary', {},
          [Button, 'raised', { text: 'raised secondary', type: 'raised', color: 'secondary' }],
          [Button, 'default-icontext', { icon: iconHappy, type: 'raised', text: 'icon text', color: 'secondary' }],
          [Button, 'raised-compact', { text: 'Compact', type: 'raised', style: 'compact', color: 'secondary' }],
          [Button, 'raised-dense', { text: 'Dense', type: 'raised', style: 'dense', color: 'secondary' }],
          [Button, 'raised-densecompact', { text: 'Compact dense', type: 'raised', style: 'compact dense', color: 'secondary' }],
          [Button, 'raised-link', { text: 'Link', type: 'raised', color: 'secondary' }]
        ],
        [Text, 'action-button', { text: 'Action Button', type: 'subheading2' }],
        [Container, 'buttons-action', {},
          [Button, 'action', { icon: iconStar, type: 'action' }],
          [Button, 'action-compact', { icon: iconHappy, type: 'action', style: 'compact' }],
          [Button, 'action-dense', { icon: iconPhone, type: 'action', style: 'dense' }],
          [Button, 'action-densecompact', { icon: iconAccessibility, type: 'action', style: 'compact dense' }],
          [Button, 'action-link', { icon: iconLink, type: 'action' }]
        ],
        [Container, 'buttons-action', {},
          [Button, 'action', { icon: iconStar, type: 'action', color: 'primary' }],
          [Button, 'action-compact', { icon: iconHappy, type: 'action', style: 'compact', color: 'primary' }],
          [Button, 'action-dense', { icon: iconPhone, type: 'action', style: 'dense', color: 'primary' }],
          [Button, 'action-densecompact', { icon: iconAccessibility, type: 'action', style: 'compact dense', color: 'primary' }],
          [Button, 'action-link', { icon: iconLink, type: 'action', color: 'primary' }]
        ],
        [Container, 'buttons-action-secondary', {},
          [Button, 'action', { icon: iconStar, type: 'action', color: 'secondary' }],
          [Button, 'action-compact', { icon: iconHappy, type: 'action', style: 'compact', color: 'secondary' }],
          [Button, 'action-dense', { icon: iconPhone, type: 'action', style: 'dense', color: 'secondary' }],
          [Button, 'action-densecompact', { icon: iconAccessibility, type: 'action', style: 'compact dense', color: 'secondary' }],
          [Button, 'action-link', { icon: iconLink, type: 'action', color: 'secondary' }]
        ],
        [Text, 'floating-button', { text: 'Floating Button', type: 'subheading2' }],
        [Container, 'buttons-floating', {},
          [Button, 'floating', { icon: iconStar, type: 'floating' }],
          [Button, 'floating-compact', { icon: iconHappy, type: 'floating', style: 'compact' }],
          [Button, 'floating-dense', { icon: iconPhone, type: 'floating', style: 'dense' }],
          [Button, 'floating-densecompact', { icon: iconAccessibility, type: 'floating', style: 'compact dense' }],
          [Button, 'floating-link', { icon: iconLink, type: 'floating', tag: 'a' }]
        ],
        [Container, 'buttons-floating', {},
          [Button, 'floating', { icon: iconStar, type: 'floating', color: 'primary' }],
          [Button, 'floating-compact', { icon: iconHappy, type: 'floating', style: 'compact', color: 'primary' }],
          [Button, 'floating-dense', { icon: iconPhone, type: 'floating', style: 'dense', color: 'primary' }],
          [Button, 'floating-densecompact', { icon: iconAccessibility, type: 'floating', style: 'compact dense', color: 'primary' }],
          [Button, 'floating-link', { icon: iconLink, type: 'floating', color: 'primary' }]
        ],
        [Container, 'buttons-floating-secondary', {},
          [Button, 'floating', { icon: iconStar, text: 'floating secondary', type: 'floating', color: 'secondary' }],
          [Button, 'floating-compact', { icon: iconHappy, text: 'Compact', type: 'floating', style: 'compact', color: 'secondary' }],
          [Button, 'floating-dense', { icon: iconPhone, text: 'Dense', type: 'floating', style: 'dense', color: 'secondary' }],
          [Button, 'floating-densecompact', { icon: iconAccessibility, type: 'floating', style: 'compact dense', color: 'secondary' }],
          [Button, 'floating-link', { icon: iconLink, type: 'floating', color: 'secondary' }]
        ]
      ]
    ]
  ], body)

  var component = layout.get()

  layout.get('default').on('click', (e) => {
    console.log('click', e, layout.get('default'))
  })

  layout.get('darktheme').on('change', function (checked) {
    console.log('darktheme', checked, layout.get('containerbutton'))
    if (checked) {
      css.add(layout.get('containerbutton').root, 'dark-theme')
    } else {
      css.remove(layout.get('containerbutton').root, 'dark-theme')
    }
  })
}
<commit_msg>Remove unused dependencies<commit_after>'use strict'

// import material components
import {
  Container,
  Checkbox,
  Button,
  Text
} from 'material'

import Layout from 'material/src/layout'
import css from 'material/src/module/css'

import iconStar from '../icon/star.svg'
import iconAccessibility from '../icon/accessibility.svg'
import iconPhone from '../icon/phone.svg'
import iconHappy from '../icon/happy.svg'
import iconLink from '../icon/link.svg'

/**
 * [initTest description]
 * @return {[type]} [description]
 */
export default function (body) {
  var layout = new Layout([Container, 'button', {},
    [Container, 'hero', {},
      [Button, 'first', { text: 'Flat' }],
      [Button, 'second', { text: 'Raised', type: 'raised', color: 'primary' }],
      [Button, 'third', { icon: iconStar, type: 'action' }],
      [Button, 'fourth', { icon: iconStar, text: 'text' }],
      [Button, 'fifth', { icon: iconStar, type: 'floating', color: 'secondary' }]
    ],
    [Container, 'containerbutton', {},
      [Container, 'options', {},
        [Checkbox, 'darktheme', { name: 'darktheme', label: 'Dark Theme' }]
      ],
      [Container, 'button-default', {},
        [Text, 'standard-button', { text: 'Standard Button', type: 'subheading2' }],
        [Container, 'buttons-container', {},
          [Button, 'default', { text: 'default' }],
          [Button, 'default-icontext', { icon: iconHappy, text: 'icon text' }],
          [Button, 'default-compact', { text: 'Compact', style: 'compact' }],
          [Button, 'default-dense', { text: 'Dense', style: 'dense' }],
          [Button, 'default-densecompact', { text: 'Compact dense', style: 'compact dense' }],
          [Button, 'default-link', { text: 'Link', tag: 'a' }]
        ],
        [Container, 'buttons-container', {},
          [Button, 'default', { text: 'default', color: 'primary' }],
          [Button, 'default-icontext', { icon: iconHappy, text: 'icon text', color: 'primary' }],
          [Button, 'default-compact', { text: 'Compact', style: 'compact', color: 'primary' }],
          [Button, 'default-dense', { text: 'Dense', style: 'dense', color: 'primary' }],
          [Button, 'default-densecompact', { text: 'Compact dense', style: 'compact dense', color: 'primary' }],
          [Button, 'default-link', { text: 'Link', color: 'primary', tag: 'a' }]
        ],
        [Container, 'buttons-container', {},
          [Button, 'default', { text: 'default', color: 'secondary' }],
          [Button, 'default-icontext', { icon: iconHappy, text: 'icon text', color: 'secondary' }],
          [Button, 'default-compact', { text: 'Compact', style: 'compact', color: 'secondary' }],
          [Button, 'default-dense', { text: 'Dense', style: 'dense', color: 'secondary' }],
          [Button, 'default-densecompact', { text: 'Compact dense', style: 'compact dense', color: 'secondary' }],
          [Button, 'default-link', { text: 'Link', color: 'secondary', tag: 'a' }]
        ],
        [Text, 'raised-button', { text: 'Raised Button', type: 'subheading2' }],
        [Container, 'buttons-raised', {},
          [Button, 'raised', { text: 'raised', type: 'raised' }],
          [Button, 'default-icontext', { icon: iconHappy, type: 'raised', text: 'icon text' }],
          [Button, 'raised-compact', { text: 'Compact', type: 'raised', style: 'compact' }],
          [Button, 'raised-dense', { text: 'Dense', type: 'raised', style: 'dense' }],
          [Button, 'raised-densecompact', { text: 'Compact dense', type: 'raised', style: 'compact dense' }],
          [Button, 'raised-link', { text: 'Link', type: 'raised' }],
          [Button, 'raised-link', { icon: iconStar, type: 'raised' }]
        ],
        [Container, 'buttons-raised-primary', {},
          [Button, 'raised', { text: 'raised primary', type: 'raised', color: 'primary' }],
          [Button, 'default-icontext', { icon: iconHappy, type: 'raised', text: 'icon text', color: 'primary' }],
          [Button, 'raised-compact', { text: 'Compact', type: 'raised', style: 'compact', color: 'primary' }],
          [Button, 'raised-dense', { text: 'Dense', style: 'dense', type: 'raised', color: 'primary' }],
          [Button, 'raised-densecompact', { text: 'Compact dense', style: 'dense compact', type: 'raised', color: 'primary' }],
          [Button, 'raised-link', { text: 'Link', type: 'raised', color: 'primary' }],
          [Button, 'raised-link', { icon: iconStar, type: 'raised', color: 'primary' }]
        ],
        [Container, 'buttons-raised-secondary', {},
          [Button, 'raised', { text: 'raised secondary', type: 'raised', color: 'secondary' }],
          [Button, 'default-icontext', { icon: iconHappy, type: 'raised', text: 'icon text', color: 'secondary' }],
          [Button, 'raised-compact', { text: 'Compact', type: 'raised', style: 'compact', color: 'secondary' }],
          [Button, 'raised-dense', { text: 'Dense', type: 'raised', style: 'dense', color: 'secondary' }],
          [Button, 'raised-densecompact', { text: 'Compact dense', type: 'raised', style: 'compact dense', color: 'secondary' }],
          [Button, 'raised-link', { text: 'Link', type: 'raised', color: 'secondary' }]
        ],
        [Text, 'action-button', { text: 'Action Button', type: 'subheading2' }],
        [Container, 'buttons-action', {},
          [Button, 'action', { icon: iconStar, type: 'action' }],
          [Button, 'action-compact', { icon: iconHappy, type: 'action', style: 'compact' }],
          [Button, 'action-dense', { icon: iconPhone, type: 'action', style: 'dense' }],
          [Button, 'action-densecompact', { icon: iconAccessibility, type: 'action', style: 'compact dense' }],
          [Button, 'action-link', { icon: iconLink, type: 'action' }]
        ],
        [Container, 'buttons-action', {},
          [Button, 'action', { icon: iconStar, type: 'action', color: 'primary' }],
          [Button, 'action-compact', { icon: iconHappy, type: 'action', style: 'compact', color: 'primary' }],
          [Button, 'action-dense', { icon: iconPhone, type: 'action', style: 'dense', color: 'primary' }],
          [Button, 'action-densecompact', { icon: iconAccessibility, type: 'action', style: 'compact dense', color: 'primary' }],
          [Button, 'action-link', { icon: iconLink, type: 'action', color: 'primary' }]
        ],
        [Container, 'buttons-action-secondary', {},
          [Button, 'action', { icon: iconStar, type: 'action', color: 'secondary' }],
          [Button, 'action-compact', { icon: iconHappy, type: 'action', style: 'compact', color: 'secondary' }],
          [Button, 'action-dense', { icon: iconPhone, type: 'action', style: 'dense', color: 'secondary' }],
          [Button, 'action-densecompact', { icon: iconAccessibility, type: 'action', style: 'compact dense', color: 'secondary' }],
          [Button, 'action-link', { icon: iconLink, type: 'action', color: 'secondary' }]
        ],
        [Text, 'floating-button', { text: 'Floating Button', type: 'subheading2' }],
        [Container, 'buttons-floating', {},
          [Button, 'floating', { icon: iconStar, type: 'floating' }],
          [Button, 'floating-compact', { icon: iconHappy, type: 'floating', style: 'compact' }],
          [Button, 'floating-dense', { icon: iconPhone, type: 'floating', style: 'dense' }],
          [Button, 'floating-densecompact', { icon: iconAccessibility, type: 'floating', style: 'compact dense' }],
          [Button, 'floating-link', { icon: iconLink, type: 'floating', tag: 'a' }]
        ],
        [Container, 'buttons-floating', {},
          [Button, 'floating', { icon: iconStar, type: 'floating', color: 'primary' }],
          [Button, 'floating-compact', { icon: iconHappy, type: 'floating', style: 'compact', color: 'primary' }],
          [Button, 'floating-dense', { icon: iconPhone, type: 'floating', style: 'dense', color: 'primary' }],
          [Button, 'floating-densecompact', { icon: iconAccessibility, type: 'floating', style: 'compact dense', color: 'primary' }],
          [Button, 'floating-link', { icon: iconLink, type: 'floating', color: 'primary' }]
        ],
        [Container, 'buttons-floating-secondary', {},
          [Button, 'floating', { icon: iconStar, text: 'floating secondary', type: 'floating', color: 'secondary' }],
          [Button, 'floating-compact', { icon: iconHappy, text: 'Compact', type: 'floating', style: 'compact', color: 'secondary' }],
          [Button, 'floating-dense', { icon: iconPhone, text: 'Dense', type: 'floating', style: 'dense', color: 'secondary' }],
          [Button, 'floating-densecompact', { icon: iconAccessibility, type: 'floating', style: 'compact dense', color: 'secondary' }],
          [Button, 'floating-link', { icon: iconLink, type: 'floating', color: 'secondary' }]
        ]
      ]
    ]
  ], body)

  var component = layout.get()

  layout.get('default').on('click', (e) => {
    console.log('click', e, layout.get('default'))
  })

  layout.get('darktheme').on('change', function (checked) {
    console.log('darktheme', checked, layout.get('containerbutton'))
    if (checked) {
      css.add(layout.get('containerbutton').root, 'dark-theme')
    } else {
      css.remove(layout.get('containerbutton').root, 'dark-theme')
    }
  })
}
<|endoftext|>