<commit_before>var unicode = require('unicode-categories');

// http://es5.github.com/#x7.6
// ECMAscript identifier starts with `$`, `_`,
// or letter from (Lu Ll Lt Lm Lo Nl) unicode groups.
// Then identifier can also be from groups (Nd, Mn, Mc, or Pc).
// Roy identifier cannot have letter u03BB (greek lowercase lambda)
// because it's used in anonymous functions.
var IDENTIFIER = new RegExp(
    unicode.ECMA.identifier.source.replace('\\u03BB', '')
);

var NUMBER = /^-?[0-9]+(\.[0-9]+)?/;
var STRING = /^("|')(?:[^"'\\]|\\.)*\1/;
var COMMENT = /^\/\/.*/;
var WHITESPACE = /^[^\n\S]+/;
var INDENT = /^(?:\n[^\n\S]*)+/;
var GENERIC = /^#([a-z]+)/;

var chunk;
var indent;
var indents;
var tokens;
var lineno;

var identifierToken = function() {
    var value,
        name,
        token = IDENTIFIER.exec(chunk);
    if(token) {
        value = token[0];
        switch(value) {
        case 'true':
        case 'false':
            name = 'BOOLEAN';
            break;
        case 'Function':
        case 'let':
        case 'if':
        case 'instance':
        case 'then':
        case 'else':
        case 'data':
        case 'type':
        case 'typeclass':
        case 'match':
        case 'case':
        case 'do':
        case 'return':
        case 'macro':
        case 'with':
        case 'where':
            name = value.toUpperCase();
            break;
        default:
            name = 'IDENTIFIER';
            break;
        }
        tokens.push([name, value, lineno]);
        return token[0].length;
    }
    return 0;
};

var numberToken = function() {
    var token = NUMBER.exec(chunk);
    if(token) {
        tokens.push(['NUMBER', token[0], lineno]);
        return token[0].length;
    }
    return 0;
};

var stringToken = function() {
  var token = STRING.exec(chunk);
  if (token) {
    tokens.push(['STRING', token[0], lineno]);
    return token[0].length;

  }
  return 0;
};

var genericToken = function() {
    var token = GENERIC.exec(chunk);
    if(token) {
        tokens.push(['GENERIC', token[1], lineno]);
        return token[0].length;
    }
    return 0;
};

var commentToken = function() {
    var token = COMMENT.exec(chunk);
    if(token) {
        tokens.push(['COMMENT', token[0], lineno]);
        return token[0].length;
    }
    return 0;
};

var whitespaceToken = function() {
    var token = WHITESPACE.exec(chunk);
    if(token) {
        return token[0].length;
    }
    return 0;
};

// If an OUTDENT is followed by a line continuer,
// the next TERMINATOR token is supressed.
var lineContinuer = {
    "where": true
};

var lineToken = function() {
    var token = INDENT.exec(chunk);
    if(token) {
        var lastNewline = token[0].lastIndexOf("\n") + 1;
        var size = token[0].length - lastNewline;
        var terminated = false;
        if(size > indent) {
            indents.push(size);
            tokens.push(['INDENT', size - indent, lineno]);
        } else {
            if(size < indent) {
                var last = indents[indents.length - 1];
                while(size < last) {
                    tokens.push(['OUTDENT', last - size, lineno]);
                    indents.pop();
                    last = indents[indents.length - 1];
                }
            }
            if(tokens.length > 0) {
                var lookahead = IDENTIFIER.exec(chunk.slice(token[0].length));

                if (!lookahead || !lineContinuer[lookahead[0]]) {
                    tokens.push(['TERMINATOR', token[0].substring(0, lastNewline), lineno]);
                }
            }
        }
        indent = size;
        return token[0].length;
    }
    return 0;
};

var literalToken = function() {
    var tag = chunk.slice(0, 1);
    var next;
    switch(tag) {
    case '<':
        next = chunk.slice(0, 2);
        if(next == '<=') {
            tokens.push(['COMPARE', next, lineno]);
            return 2;
        } else if(next == '<-') {
            tokens.push(['LEFTARROW', next, lineno]);
            return 2;
        } else if(next == '<<') {
            tokens.push(['MATH', next, lineno]);
            return 2;
        }
        tokens.push(['COMPARE', tag, lineno]);
        return 1;
    case '>':
        next = chunk.slice(0, 2);
        if(next == '>=') {
            tokens.push(['COMPARE', next, lineno]);
            return 2;
        } else if(next == '>>') {
            tokens.push(['MATH', next, lineno]);
            return 2;
        }
        tokens.push(['COMPARE', tag, lineno]);
        return 1;
    case '=':
        next = chunk.slice(0, 2);
        if(next == '==') {
            tokens.push(['COMPARE', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '!':
        next = chunk.slice(0, 2);
        if(next == '!=') {
            tokens.push(['COMPARE', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '*':
    case '/':
    case '%':
        tokens.push(['MATH', tag, lineno]);
        return 1;
    case '[':
    case '|':
        next = chunk.slice(0, 2);
        switch(next) {
        case '[|':
        case '|]':
            tokens.push([next, next, lineno]);
            return 2;
        case '||':
            tokens.push(['BOOLOP', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case ')':
        if(tokens[tokens.length-1][0] == 'TERMINATOR') {
            tokens.pop();
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '+':
        next = chunk.slice(0, 2);
        if(next == '++') {
            tokens.push(['CONCAT', tag, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '-':
        next = chunk.slice(0, 2);
        if (next == '->') {
            tokens.push(['RIGHTARROW', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '&':
        next = chunk.slice(0, 2);
        if(next == '&&') {
            tokens.push(['BOOLOP', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case 'λ':
    case '\\':
        tokens.push(['LAMBDA', tag, lineno]);
        return 1;
    case '←':
        tokens.push(['LEFTARROW', tag, lineno]);
        return 1;
    case '→':
        tokens.push(['RIGHTARROW', tag, lineno]);
        return 1;
    case '⇒':
        tokens.push(['RIGHTFATARROW', tag, lineno]);
        return 1;
    case '@':
    case ']':
    case ':':
    case '.':
    case ',':
    case '{':
    case '}':
    case '(':
        tokens.push([tag, tag, lineno]);
        return 1;
    }
    return 0;
};

exports.tokenise = function(source) {
    indent = 0;
    indents = [];
    tokens = [];
    lineno = 0;
    var i = 0;
    while(chunk = source.slice(i)) {
        var diff = identifierToken() || numberToken() || stringToken() || genericToken() || commentToken() || whitespaceToken() || lineToken() || literalToken();
        if(!diff) {
            throw "Couldn't tokenise: " + chunk.substring(0, chunk.indexOf("\n") > -1 ? chunk.indexOf("\n") : chunk.length);
        }
        lineno += source.slice(i, i + diff).split('\n').length - 1;
        i += diff;
    }
    tokens.push(['EOF', '', lineno]);
    return tokens;
};
<commit_msg>Update src/lexer.js<commit_after>var unicode = require('unicode-categories');

// http://es5.github.com/#x7.6
// ECMAscript identifier starts with `$`, `_`,
// or letter from (Lu Ll Lt Lm Lo Nl) unicode groups.
// Then identifier can also be from groups (Nd, Mn, Mc, or Pc).
// Roy identifier cannot have letter u03BB (greek lowercase lambda)
// because it's used in anonymous functions.
var IDENTIFIER = new RegExp(
    unicode.ECMA.identifier.source.replace('\\u03BB', '')
);

var NUMBER = /^-?[0-9]+(\.[0-9]+)?/;
var STRING = /^(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/;
var COMMENT = /^\/\/.*/;
var WHITESPACE = /^[^\n\S]+/;
var INDENT = /^(?:\n[^\n\S]*)+/;
var GENERIC = /^#([a-z]+)/;

var chunk;
var indent;
var indents;
var tokens;
var lineno;

var identifierToken = function() {
    var value,
        name,
        token = IDENTIFIER.exec(chunk);
    if(token) {
        value = token[0];
        switch(value) {
        case 'true':
        case 'false':
            name = 'BOOLEAN';
            break;
        case 'Function':
        case 'let':
        case 'if':
        case 'instance':
        case 'then':
        case 'else':
        case 'data':
        case 'type':
        case 'typeclass':
        case 'match':
        case 'case':
        case 'do':
        case 'return':
        case 'macro':
        case 'with':
        case 'where':
            name = value.toUpperCase();
            break;
        default:
            name = 'IDENTIFIER';
            break;
        }
        tokens.push([name, value, lineno]);
        return token[0].length;
    }
    return 0;
};

var numberToken = function() {
    var token = NUMBER.exec(chunk);
    if(token) {
        tokens.push(['NUMBER', token[0], lineno]);
        return token[0].length;
    }
    return 0;
};

var stringToken = function() {
  var token = STRING.exec(chunk);
  if (token) {
    tokens.push(['STRING', token[0], lineno]);
    return token[0].length;

  }
  return 0;
};

var genericToken = function() {
    var token = GENERIC.exec(chunk);
    if(token) {
        tokens.push(['GENERIC', token[1], lineno]);
        return token[0].length;
    }
    return 0;
};

var commentToken = function() {
    var token = COMMENT.exec(chunk);
    if(token) {
        tokens.push(['COMMENT', token[0], lineno]);
        return token[0].length;
    }
    return 0;
};

var whitespaceToken = function() {
    var token = WHITESPACE.exec(chunk);
    if(token) {
        return token[0].length;
    }
    return 0;
};

// If an OUTDENT is followed by a line continuer,
// the next TERMINATOR token is supressed.
var lineContinuer = {
    "where": true
};

var lineToken = function() {
    var token = INDENT.exec(chunk);
    if(token) {
        var lastNewline = token[0].lastIndexOf("\n") + 1;
        var size = token[0].length - lastNewline;
        var terminated = false;
        if(size > indent) {
            indents.push(size);
            tokens.push(['INDENT', size - indent, lineno]);
        } else {
            if(size < indent) {
                var last = indents[indents.length - 1];
                while(size < last) {
                    tokens.push(['OUTDENT', last - size, lineno]);
                    indents.pop();
                    last = indents[indents.length - 1];
                }
            }
            if(tokens.length > 0) {
                var lookahead = IDENTIFIER.exec(chunk.slice(token[0].length));

                if (!lookahead || !lineContinuer[lookahead[0]]) {
                    tokens.push(['TERMINATOR', token[0].substring(0, lastNewline), lineno]);
                }
            }
        }
        indent = size;
        return token[0].length;
    }
    return 0;
};

var literalToken = function() {
    var tag = chunk.slice(0, 1);
    var next;
    switch(tag) {
    case '<':
        next = chunk.slice(0, 2);
        if(next == '<=') {
            tokens.push(['COMPARE', next, lineno]);
            return 2;
        } else if(next == '<-') {
            tokens.push(['LEFTARROW', next, lineno]);
            return 2;
        } else if(next == '<<') {
            tokens.push(['MATH', next, lineno]);
            return 2;
        }
        tokens.push(['COMPARE', tag, lineno]);
        return 1;
    case '>':
        next = chunk.slice(0, 2);
        if(next == '>=') {
            tokens.push(['COMPARE', next, lineno]);
            return 2;
        } else if(next == '>>') {
            tokens.push(['MATH', next, lineno]);
            return 2;
        }
        tokens.push(['COMPARE', tag, lineno]);
        return 1;
    case '=':
        next = chunk.slice(0, 2);
        if(next == '==') {
            tokens.push(['COMPARE', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '!':
        next = chunk.slice(0, 2);
        if(next == '!=') {
            tokens.push(['COMPARE', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '*':
    case '/':
    case '%':
        tokens.push(['MATH', tag, lineno]);
        return 1;
    case '[':
    case '|':
        next = chunk.slice(0, 2);
        switch(next) {
        case '[|':
        case '|]':
            tokens.push([next, next, lineno]);
            return 2;
        case '||':
            tokens.push(['BOOLOP', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case ')':
        if(tokens[tokens.length-1][0] == 'TERMINATOR') {
            tokens.pop();
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '+':
        next = chunk.slice(0, 2);
        if(next == '++') {
            tokens.push(['CONCAT', tag, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '-':
        next = chunk.slice(0, 2);
        if (next == '->') {
            tokens.push(['RIGHTARROW', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '&':
        next = chunk.slice(0, 2);
        if(next == '&&') {
            tokens.push(['BOOLOP', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case 'λ':
    case '\\':
        tokens.push(['LAMBDA', tag, lineno]);
        return 1;
    case '←':
        tokens.push(['LEFTARROW', tag, lineno]);
        return 1;
    case '→':
        tokens.push(['RIGHTARROW', tag, lineno]);
        return 1;
    case '⇒':
        tokens.push(['RIGHTFATARROW', tag, lineno]);
        return 1;
    case '@':
    case ']':
    case ':':
    case '.':
    case ',':
    case '{':
    case '}':
    case '(':
        tokens.push([tag, tag, lineno]);
        return 1;
    }
    return 0;
};

exports.tokenise = function(source) {
    indent = 0;
    indents = [];
    tokens = [];
    lineno = 0;
    var i = 0;
    while(chunk = source.slice(i)) {
        var diff = identifierToken() || numberToken() || stringToken() || genericToken() || commentToken() || whitespaceToken() || lineToken() || literalToken();
        if(!diff) {
            throw "Couldn't tokenise: " + chunk.substring(0, chunk.indexOf("\n") > -1 ? chunk.indexOf("\n") : chunk.length);
        }
        lineno += source.slice(i, i + diff).split('\n').length - 1;
        i += diff;
    }
    tokens.push(['EOF', '', lineno]);
    return tokens;
};
<|endoftext|>


<commit_before>var Commands = function(hostline, user, group) {
    // Various dd parameters
    exponent = Math.floor((Math.random() * 4));
    hd_size = 64 << exponent;            // Random but within the specified range
    dd_duration = (hd_size >> 6) * 500;  // Make the base length stable
    dd_device = 'sda'                    // This probably won't gain 'coolness' from changing
    dd_block_size = 4                    // Assumed MB

    var formatSpaces = function (name, spaces) {
        emptyString = '';
        while (emptyString.length < spaces) emptyString += ' ';

        return (name + emptyString).slice(0, spaces);
    }

    var padNumber = function (value, spaces) {
        emptyString = '';
        while (emptyString.length < spaces) emptyString += '0';

        return (emptyString + value).slice(('' + value).length);
    }

    var softLink = function (user, group, source, target) {
        return 'lrwxrwxrwx   1 ' + formatSpaces(user, 5) + ' ' + formatSpaces(group, 5) + '    35 Mar 29  2013 ' +
               '' + source + '' +
               ' -> ' +
               '' + target + '';
    }

    var ddCopyOutput = function (device, size_gb, block_size, duration) {
        records = (size_gb << 10) / block_size;
        variance = Math.random();
        true_duration = duration/1000.0 + variance;
        throughput = size_gb / true_duration;

        // This is stupid but JS seems to roll over at a certain point for ints 2^32 < x < 2^64
        // so we do this digit-trim hack to display it correctly
        bytes_copied = (size_gb << 20) / 1000;
        bytes_copied <<= 10;

        return records + '+0 records in\n' +
               records + '+0 records out\n' +
               bytes_copied + '000 bytes (' + size_gb + ' GB) copied, ' +
                 true_duration.toFixed(5) + ' s, ' + throughput.toFixed(1) + ' GB/s';
    }

    return { 'poweroff':     { typedCommand: "poweroff",
                               startDelay: 1250,
                               hesitation: 200,
                               duration: 0,
                               output: "\nBroadcast message from " + hostline + "\n\t\t(/dev/pts/0) at " +
                                       padNumber(new Date().getHours(), 2) + ":" +
                                       padNumber(new Date().getMinutes(), 2) + "...\n\n" +
                                       "The system is going down for halt NOW!"
                             },
             'get_users':    { typedCommand: 'cat /etc/passwd | grep \'/home/\' | grep \'^[^:]*:x:[0-9]\\{4\\}:\' | awk -F: \'{print $1}\'',
                               startDelay: 1250,
                               hesitation: 200,
                               duration: 100,
                               output: user
                             },
             'ls_home':      { typedCommand: 'ls -la ~' + user,
                               startDelay: 1250,
                               hesitation: 200,
                               duration: 100,
                               output: 'drwx------ 113 ' + formatSpaces(user, 5) + ' ' + formatSpaces(group, 5) + ' 36864 Jul 24 22:38 .\n' +
                                       'drwxr-xr-x   6 ' + formatSpaces('root', 5) + ' ' + formatSpaces('root', 5) + '  4096 Jan  6  2015 ..\n' +
                                       softLink(user, group, 'github', 'https://github.com/sgnn7') + '\n' +
                                       softLink(user, group, 'twitter', 'https://twitter.com/sgnn7') + '\n' +
                                       softLink(user, group, 'linkedin', 'https://linkedin.com/in/sgnn7')
                             },
             'dd_partition': { typedCommand: 'dd if=/dev/urandom of=/dev/' + dd_device + ' bs=' + dd_block_size + 'M',
                               startDelay: 1200,
                               hesitation: 3000,
                               duration: dd_duration,
                               output: ddCopyOutput(dd_device, hd_size, dd_block_size, dd_duration)
                             },
            };
};

var Scroller = function(target){
    hostline = "root@" + (window.location.hostname || 'localhost');
    bash_prompt = '' + hostline + '' +
                  ':' +
                  '~' +
                  '# ';

    commands = new Commands(hostline, 'sg', 'sg');

    textSpeed = 19;
    textSpeedJitter = 12;
    textStartSpeed = 800;
    newlineSpeed = 400;
    promptDelay = 1000;

    textPos = 0;

    commandList = ['get_users', 'ls_home', 'dd_partition', 'poweroff'];

    cursorSpeed = 500;
    cursorShowing = false;
    cursorStates = ['_', ' '];

    addTextInstant = function(targetElement, text) {
        // console.log(target);

        var oldText = targetElement.innerHTML;
        targetElement.innerHTML = oldText + text;
    };

    removeCursor = function(targetElement) {
        var oldText = targetElement.innerHTML;
        targetElement.innerHTML = oldText.substring(0, oldText.length - 1);
    };

    addPrompt = function(targetElement) {
        addTextInstant(targetElement, bash_prompt);
    };

    // TODO: Do something with this (if anything)
    updateCursorState = function(text) {
        var oldText = document.getElementById(target).innerHTML || "";

        if (!text) {
            oldText += " ";
        }

        this.cursorShowing = !this.cursorShowing;

        newText = oldText.substring(0, oldText.length - 1) + this.cursorStates[ this.cursorShowing ? 0 : 1 ];
        document.getElementById(target).innerHTML = newText;
        setTimeout(function() {
                        this.updateCursorState(newText);
                   },
                   this.cursorSpeed);
    };

    addTypedText = function(targetElement, typedText, commandIndex, originalText, textIndex) {
        // Could have assumed ECMA6 and done default params but this is more compatible
        if (!originalText)
            originalText = targetElement.innerHTML;

        if (!textIndex)
            textIndex = 0;

        this.addTextInstant(targetElement, typedText.substring(textIndex, textIndex + 1));

        if (textIndex <= typedText.length) {
            textIndex++;
            if (typedText.substring(textIndex - 1, textIndex) == '\n') {
                this.addTextInstant('_');
                setTimeout(function() {
                               printCommandOutput(targetElement, command, commandIndex);
                           },
                           command.hesitation);
            } else {
                randomJitter = this.textSpeedJitter * Math.random();
                jitteredTextSpeed = this.textSpeed + (randomJitter / 2);

                // console.log("Jitter:", jitteredTextSpeed);

                setTimeout(function() {
                               this.addTypedText(targetElement, typedText, commandIndex, originalText, textIndex);
                           },
                           jitteredTextSpeed);
            }
        }
    };

    typeCommand = function(targetElement, command, index) {
        addTypedText(targetElement, command.typedCommand + '\n', index);
    };

    // Prints the prompt and executes a single command and displays it's output
    printCommandOutput = function(targetElement, command, commandIndex) {
        removeCursor(targetElement);

        var outputElement = document.createElement('p');
        outputElement.className += "command-output";

        targetElement.appendChild(outputElement);
        addTextInstant(outputElement, command.output);

        setTimeout(function() {
                       executeCommands(targetElement, commandIndex + 1);
                   },
                   promptDelay);
    };

    // Prints the prompt, types the command, and then executes it
    executeCommand = function(targetElement, commandIndex) {
        commandName = commandList[commandIndex];
        command = commands[commandName];
        console.log('Command: ' + commandName);

        addPrompt(targetElement);

        setTimeout(function() {
                       typeCommand(targetElement, command, commandIndex);
                   },
                   command.startDelay);
    };

    // Executes one command at a time from the commandList
    executeCommands = function(targetElement, commandIndex) {
        if (!commandIndex)
            commandIndex = 0;

        if (commandIndex >= commandList.length)
            return;

        var targetElement = document.createElement('p');
        targetElement.id = 'command_' + commandIndex;

        document.getElementById(target).appendChild(targetElement);

        executeCommand(targetElement, commandIndex);
    };

    executeCommands();
}
<commit_msg>Extracted util functions out of main classes<commit_after>// Helper class
utils = { 'spanText':     function(clazz, text) {
                              return '' + text + '';
                          },

          'formatSpaces': function (name, spaces) {
                              var emptyString = '';
                              while (emptyString.length < spaces) emptyString += ' ';

                              return (name + emptyString).slice(0, spaces);
                          },

          'padNumber':    function (value, spaces) {
                              var emptyString = '';
                              while (emptyString.length < spaces) emptyString += '0';

                              return (emptyString + value).slice(('' + value).length);
                           }
}

var Commands = function(hostline, user, group) {
    // Various dd parameters
    exponent = Math.floor((Math.random() * 4));
    hd_size = 64 << exponent;            // Random but within the specified range
    dd_duration = (hd_size >> 6) * 500;  // Make the base length stable
    dd_device = 'sda'                    // This probably won't gain 'coolness' from changing
    dd_block_size = 4                    // Assumed MB

    var softLink = function (user, group, source, target) {
        return 'lrwxrwxrwx   1 ' + utils.formatSpaces(user, 5) + ' ' + utils.formatSpaces(group, 5) + '    35 Mar 29  2013 ' +
               utils.spanText('softlink', source) +
               ' -> ' +
               '' + target + '';
    }

    var ddCopyOutput = function (device, size_gb, block_size, duration) {
        var records = (size_gb << 10) / block_size;
        var variance = Math.random();
        var true_duration = duration/1000.0 + variance;
        var throughput = size_gb / true_duration;

        // This is stupid but JS seems to roll over at a certain point for ints 2^32 < x < 2^64
        // so we do this digit-trim hack to display it correctly
        var bytes_copied = (size_gb << 20) / 1000;
        bytes_copied <<= 10;

        return records + '+0 records in\n' +
               records + '+0 records out\n' +
               bytes_copied + '000 bytes (' + size_gb + ' GB) copied, ' +
                 true_duration.toFixed(5) + ' s, ' + throughput.toFixed(1) + ' GB/s';
    }

    return { 'poweroff':     { typedCommand: "poweroff",
                               startDelay: 1250,
                               hesitation: 200,
                               duration: 0,
                               output: "\nBroadcast message from " + hostline + "\n\t\t(/dev/pts/0) at " +
                                       utils.padNumber(new Date().getHours(), 2) + ":" +
                                       utils.padNumber(new Date().getMinutes(), 2) + "...\n\n" +
                                       "The system is going down for halt NOW!"
                             },
             'get_users':    { typedCommand: 'cat /etc/passwd | grep \'/home/\' | grep \'^[^:]*:x:[0-9]\\{4\\}:\' | awk -F: \'{print $1}\'',
                               startDelay: 1250,
                               hesitation: 200,
                               duration: 100,
                               output: user
                             },
             'ls_home':      { typedCommand: 'ls -la ~' + user,
                               startDelay: 1250,
                               hesitation: 200,
                               duration: 100,
                               output: 'drwx------ 113 ' + utils.formatSpaces(user, 5) + ' ' + utils.formatSpaces(group, 5) + ' 36864 Jul 24 22:38 .\n' +
                                       'drwxr-xr-x   6 ' + utils.formatSpaces('root', 5) + ' ' + utils.formatSpaces('root', 5) + '  4096 Jan  6  2015 ..\n' +
                                       softLink(user, group, 'github', 'https://github.com/sgnn7') + '\n' +
                                       softLink(user, group, 'twitter', 'https://twitter.com/sgnn7') + '\n' +
                                       softLink(user, group, 'linkedin', 'https://linkedin.com/in/sgnn7')
                             },
             'dd_partition': { typedCommand: 'dd if=/dev/urandom of=/dev/' + dd_device + ' bs=' + dd_block_size + 'M',
                               startDelay: 1200,
                               hesitation: 3000,
                               duration: dd_duration,
                               output: ddCopyOutput(dd_device, hd_size, dd_block_size, dd_duration)
                             },
            };
};

var Scroller = function(target){
    hostline = "root@" + (window.location.hostname || 'localhost');
    bash_prompt = utils.spanText('prompt-hostline', hostline) +
                  utils.spanText('prompt-normal', ":") +
                  utils.spanText('prompt-path', "~") +
                  utils.spanText('prompt-normal', "# ");

    commands = new Commands(hostline, 'sg', 'sg');

    textSpeed = 19;
    textSpeedJitter = 12;
    textStartSpeed = 800;
    newlineSpeed = 400;
    promptDelay = 1000;

    textPos = 0;

    commandList = ['get_users', 'ls_home', 'dd_partition', 'poweroff'];

    cursorSpeed = 500;
    cursorShowing = false;
    cursorStates = ['_', ' '];

    addTextInstant = function(targetElement, text) {
        // console.log(target);

        var oldText = targetElement.innerHTML;
        targetElement.innerHTML = oldText + text;
    };

    removeCursor = function(targetElement) {
        var oldText = targetElement.innerHTML;
        targetElement.innerHTML = oldText.substring(0, oldText.length - 1);
    };

    addPrompt = function(targetElement) {
        addTextInstant(targetElement, bash_prompt);
    };

    // TODO: Do something with this (if anything)
    updateCursorState = function(text) {
        var oldText = document.getElementById(target).innerHTML || "";

        if (!text) {
            oldText += " ";
        }

        this.cursorShowing = !this.cursorShowing;

        newText = oldText.substring(0, oldText.length - 1) + this.cursorStates[ this.cursorShowing ? 0 : 1 ];
        document.getElementById(target).innerHTML = newText;
        setTimeout(function() {
                        this.updateCursorState(newText);
                   },
                   this.cursorSpeed);
    };

    addTypedText = function(targetElement, typedText, commandIndex, originalText, textIndex) {
        // Could have assumed ECMA6 and done default params but this is more compatible
        if (!originalText)
            originalText = targetElement.innerHTML;

        if (!textIndex)
            textIndex = 0;

        this.addTextInstant(targetElement, typedText.substring(textIndex, textIndex + 1));

        if (textIndex <= typedText.length) {
            textIndex++;
            if (typedText.substring(textIndex - 1, textIndex) == '\n') {
                this.addTextInstant('_');
                setTimeout(function() {
                               printCommandOutput(targetElement, command, commandIndex);
                           },
                           command.hesitation);
            } else {
                randomJitter = this.textSpeedJitter * Math.random();
                jitteredTextSpeed = this.textSpeed + (randomJitter / 2);

                // console.log("Jitter:", jitteredTextSpeed);

                setTimeout(function() {
                               this.addTypedText(targetElement, typedText, commandIndex, originalText, textIndex);
                           },
                           jitteredTextSpeed);
            }
        }
    };

    typeCommand = function(targetElement, command, index) {
        addTypedText(targetElement, command.typedCommand + '\n', index);
    };

    // Prints the prompt and executes a single command and displays it's output
    printCommandOutput = function(targetElement, command, commandIndex) {
        removeCursor(targetElement);

        var outputElement = document.createElement('p');
        outputElement.className += "command-output";

        targetElement.appendChild(outputElement);
        addTextInstant(outputElement, command.output);

        setTimeout(function() {
                       executeCommands(targetElement, commandIndex + 1);
                   },
                   promptDelay);
    };

    // Prints the prompt, types the command, and then executes it
    executeCommand = function(targetElement, commandIndex) {
        commandName = commandList[commandIndex];
        command = commands[commandName];
        console.log('Command: ' + commandName);

        addPrompt(targetElement);

        setTimeout(function() {
                       typeCommand(targetElement, command, commandIndex);
                   },
                   command.startDelay);
    };

    // Executes one command at a time from the commandList
    executeCommands = function(targetElement, commandIndex) {
        if (!commandIndex)
            commandIndex = 0;

        if (commandIndex >= commandList.length)
            return;

        var targetElement = document.createElement('p');
        targetElement.id = 'command_' + commandIndex;

        document.getElementById(target).appendChild(targetElement);

        executeCommand(targetElement, commandIndex);
    };

    executeCommands();
}
<|endoftext|>


<commit_before>/**
 * Copyright 2014 LaxarJS
 * Released under the MIT license.
 * www.laxarjs.org
 */
define( [
   'angular',
   'laxar',
   'laxar_patterns',
   'angular-nvd3',
   'css!nvd3'
], function( ng, ax, patterns ) {
   'use strict';

   var moduleName = 'widgets.chart_demo.chart_widget';
   var module     = ng.module( moduleName, [ 'nvd3' ] );

   ///////////////////////////////////////////////////////////////////////////////////////////////////////////

   // Chart Styling

   var MARGIN_TOP = 20;
   var MARGIN_RIGHT = 20;
   var MARGIN_BOTTOM = 40;
   var MARGIN_LEFT = 55;
   var Y_AXIS_LABEL_DISTANCE = 30;

   ///////////////////////////////////////////////////////////////////////////////////////////////////////////

   Controller.$inject = [ '$scope' ];

   function Controller( $scope ) {
      $scope.model = {};
      $scope.resources = {};
      var model = $scope.model;
      var resources = $scope.resources;
      var features = $scope.features;

      patterns.resources.handlerFor( $scope ).registerResourceFromFeature( 'display',
         { onUpdateReplace: [ convertToChartModel, setOptionsFromResource ] } );

      setOptions();

      ////////////////////////////////////////////////////////////////////////////////////////////////////////

      function convertToChartModel() {
         if( features.display.chart.type === 'pieChart' ) {
            model.data = resources.display.series.map( function( seriesObject ) {
               var averageValue = calculateAverageValue( seriesObject.values );
               var obj = {
                  x: seriesObject.label,
                  y: averageValue
               };
               return obj;
            } );
         }
         else {
            model.data = [];
            resources.display.series.forEach( function( seriesObject, key ) {
               var values= [];
               seriesObject.values.forEach( function( value, timeTickKey ) {
                  values.push( {
                     x: resources.display.timeGrid[ timeTickKey ],
                     y: value
                  } );
               } );

               model.data.push( {
                  values: values,
                  key: seriesObject.label
               } );
            } );
         }
      }

      ////////////////////////////////////////////////////////////////////////////////////////////////////////

      function calculateAverageValue( values ){
         var sum = 0;
         values.forEach( function( value ) {
            sum = sum + value;
         } );
         return Math.round( sum * 10 / values.length ) / 10;
      }

      ////////////////////////////////////////////////////////////////////////////////////////////////////////

      function setOptionsFromResource() {
         model.options.chart.xAxis.tickValues = resources.display.timeGrid;
         model.options.chart.xAxis.axisLabel = resources.display.timeLabel;
         model.options.chart.yAxis.axisLabel =  resources.display.valueLabel;
      }

      ////////////////////////////////////////////////////////////////////////////////////////////////////////

      function setOptions() {
         model.options = {
            chart: {
               type: features.display.chart.type,
               margin: {
                  top: MARGIN_TOP,
                  right: MARGIN_RIGHT,
                  bottom: MARGIN_BOTTOM,
                  left: MARGIN_LEFT
               },
               useInteractiveGuideline: true,
               xAxis: {
               },
               yAxis: {
                  axisLabelDistance: Y_AXIS_LABEL_DISTANCE
               },
               callback: function() {
                  //ax.log.debug('!!! lineChart callback !!!');
               }
            }
         };
         model.options.chart.height = features.display.chart.height;
         if(  features.display.chart.type === 'pieChart' ) {
            model.options.chart.pie = {};
         }
      }
   }

   module.controller( moduleName + '.Controller', Controller );

   ///////////////////////////////////////////////////////////////////////////////////////////////////////////

   return module;

} );
<commit_msg>OSS-74: wip<commit_after>/**
 * Copyright 2014 LaxarJS
 * Released under the MIT license.
 * www.laxarjs.org
 */
define( [
   'angular',
   'laxar',
   'laxar_patterns',
   'angular-nvd3',
   'css!nvd3'
], function( ng, ax, patterns ) {
   'use strict';

   var moduleName = 'widgets.chart_demo.chart_widget';
   var module     = ng.module( moduleName, [ 'nvd3' ] );

   ///////////////////////////////////////////////////////////////////////////////////////////////////////////

   // Chart Styling

   var MARGIN_TOP = 20;
   var MARGIN_RIGHT = 20;
   var MARGIN_BOTTOM = 40;
   var MARGIN_LEFT = 55;
   var Y_AXIS_LABEL_DISTANCE = 30;

   ///////////////////////////////////////////////////////////////////////////////////////////////////////////

   Controller.$inject = [ '$scope' ];

   function Controller( $scope ) {
      $scope.model = {};
      $scope.resources = {};
      var model = $scope.model;
      var resources = $scope.resources;
      var features = $scope.features;

      patterns.resources.handlerFor( $scope ).registerResourceFromFeature( 'display',
         { onUpdateReplace: [ convertToChartModel, setOptionsFromResource ] } );

      setOptions();

      ////////////////////////////////////////////////////////////////////////////////////////////////////////

      function convertToChartModel() {
         if( features.display.chart.type === 'pieChart' ) {
            model.data = resources.display.series.map( function( seriesObject ) {
               var averageValue = calculateAverageValue( seriesObject.values );
               var obj = {
                  x: seriesObject.label,
                  y: averageValue
               };
               return obj;
            } );
         }
         else {
            model.data = [];
            resources.display.series.forEach( function( seriesObject, key ) {
               var values= [];
               seriesObject.values.forEach( function( value, timeTickKey ) {
                  values.push( {
                     x: resources.display.timeGrid[ timeTickKey ],
                     y: value
                  } );
               } );

               model.data.push( {
                  values: values,
                  key: seriesObject.label
               } );
            } );
         }
      }

      ////////////////////////////////////////////////////////////////////////////////////////////////////////

      function calculateAverageValue( values ){
         var sum = 0;
         values.forEach( function( value ) {
            sum = sum + value;
         } );
         return Math.round( sum * 10 / values.length ) / 10;
      }

      ////////////////////////////////////////////////////////////////////////////////////////////////////////

      function setOptionsFromResource() {
         //model.options.chart.xAxis.tickValues = resources.display.timeGrid;
         model.options.chart.xAxis.axisLabel = resources.display.timeLabel;
         model.options.chart.yAxis.axisLabel =  resources.display.valueLabel;
      }

      ////////////////////////////////////////////////////////////////////////////////////////////////////////

      function setOptions() {
         model.options = {
            chart: {
               type: features.display.chart.type,
               margin: {
                  top: MARGIN_TOP,
                  right: MARGIN_RIGHT,
                  bottom: MARGIN_BOTTOM,
                  left: MARGIN_LEFT
               },
               useInteractiveGuideline: true,
               xAxis: {
               },
               yAxis: {
                  axisLabelDistance: Y_AXIS_LABEL_DISTANCE
               },
               callback: function() {
                  //ax.log.debug('!!! lineChart callback !!!');
               }
            }
         };
         model.options.chart.height = features.display.chart.height;
         if(  features.display.chart.type === 'pieChart' ) {
            model.options.chart.pie = {};
         }
      }
   }

   module.controller( moduleName + '.Controller', Controller );

   ///////////////////////////////////////////////////////////////////////////////////////////////////////////

   return module;

} );
<|endoftext|>


<commit_before>import {
    UPDATE_GRAPH,
    UPDATE_NODE,
    UPDATE_NODES,
    UPDATE_NODES_AND_GRAPH,
    SET_CURRENT_PIPELINE
} from './actions';

import {List} from 'immutable';

const initState = {
    graph: {},
    nodes: {},
    currentNode: null,
    nodeHistory: new List(),
    inspected: null
};

export const reducer = (state = initState, action) => {
    switch (action.type) {
        case UPDATE_GRAPH: {
            return {...state, graph: action.payload};
        }
        case UPDATE_NODE: {
            return {
                ...state,
                nodes: {...state.nodes, [action.payload.id]: action.payload.value}
            };
        }
        case UPDATE_NODES: {
            return {...state, nodes: action.payload};
        }
        case UPDATE_NODES_AND_GRAPH: {
            return {
                ...state,
                nodes: action.payload.nodes,
                graph: action.payload.graph
            };
        }
        case SET_CURRENT_PIPELINE: {
            const pipelineId = action.payload.id;
            const nodeIndex = state.nodeHistory.findIndex(node => node === pipelineId);
            const currentIndex = state.nodeHistory.findIndex(node => node === state.currentNode);
            if (nodeIndex > -1) {
                return {...state, currentNode: pipelineId};
            } else {
                if (action.meta.appendToHistory) {
                    const newHistory = state.nodeHistory.splice(currentIndex + 1);
                    return {
                        ...state,
                        nodeHistory: newHistory.push(pipelineId),
                        currentNode: pipelineId
                    };
                } else {
                    return {...state, nodeHistory: new List([pipelineId]), currentNode: pipelineId};
                }
            }
        }
        default: {
            return state;
        }
    }
};
<commit_msg>fix: correctly update node history when a node is deleted<commit_after>import {
    UPDATE_GRAPH,
    UPDATE_NODE,
    UPDATE_NODES,
    UPDATE_NODES_AND_GRAPH,
    SET_CURRENT_PIPELINE,
    DELETE_NODE
} from './actions';

import {List} from 'immutable';

const initState = {
    graph: {},
    nodes: {},
    currentNode: null,
    nodeHistory: new List(),
    inspected: null
};

export const reducer = (state = initState, action) => {
    switch (action.type) {
        case UPDATE_GRAPH: {
            return {...state, graph: action.payload};
        }
        case UPDATE_NODE: {
            return {
                ...state,
                nodes: {...state.nodes, [action.payload.id]: action.payload.value}
            };
        }
        case UPDATE_NODES: {
            return {...state, nodes: action.payload};
        }
        case UPDATE_NODES_AND_GRAPH: {
            return {
                ...state,
                nodes: action.payload.nodes,
                graph: action.payload.graph
            };
        }
        case DELETE_NODE: {
            const nodeId = action.payload;
            const nodeIndex = state.nodeHistory.indexOf(nodeId);
            if (nodeIndex !== -1) {
                return {
                    ...state,
                    nodeHistory: state.nodeHistory.remove(nodeIndex)
                }
            } else {
                return state;
            }
        }
        case SET_CURRENT_PIPELINE: {
            const pipelineId = action.payload.id;
            const nodeIndex = state.nodeHistory.findIndex(node => node === pipelineId);
            const currentIndex = state.nodeHistory.findIndex(node => node === state.currentNode);
            if (nodeIndex > -1) {
                return {...state, currentNode: pipelineId};
            } else {
                if (action.meta.appendToHistory) {
                    const newHistory = state.nodeHistory.splice(currentIndex + 1);
                    return {
                        ...state,
                        nodeHistory: newHistory.push(pipelineId),
                        currentNode: pipelineId
                    };
                } else {
                    return {...state, nodeHistory: new List([pipelineId]), currentNode: pipelineId};
                }
            }
        }
        default: {
            return state;
        }
    }
};
<|endoftext|>


<commit_before><commit_msg>delete stale code<commit_after><|endoftext|>


<commit_before>var fs = require('fs');
var template = getTemplate();
var demoHome = null;
var outputHome = process.argv.length > 2 ? process.argv[2] : './live-demo/';

if (fs.existsSync(outputHome)) {
    console.error("ERROR: remove output dir and try again: " + outputHome);
    process.exit(1);
}
outputHome = outputHome ? outputHome.trim() : './live-demo/';
var outputHomeRoot = outputHome.match(/[\/\\]$/) ? outputHome : outputHome + '/';

makeAllPlunkers('e2e-testee');
makeAllPlunkers('live-demo');

function makeAllPlunkers(dirName) {
    demoHome = getDemoHome(dirName);
    outputHome = outputHomeRoot + dirName + '/';
    var demoSetFolders = fs.readdirSync(demoHome);
    demoSetFolders.forEach(demoFolder => {
        var pathname = demoHome + demoFolder;
        var stat = fs.lstatSync(pathname);
        if (stat.isDirectory()) {
            if(dirName == 'live-demo'){
                makePlunker(pathname + '/');
            } else if(dirName == 'e2e-testee') {
                processDemoSet(pathname + '/');
            }
        }
    });
}

function processDemoSet(demoSetFolder) {
    var demoFolders = fs.readdirSync(demoSetFolder);
    demoFolders.forEach(demoFolder => {
        var pathname = demoSetFolder + demoFolder;
        var stat = fs.lstatSync(pathname);
        if (stat.isDirectory()) {
            makePlunker(pathname + '/');
        }
    });
}

function makePlunker(demoFolder) {
    var content = [];
    var mockDatas = [];
    readDemoContent(content, demoFolder);
    var compContentIndex = -1;
    var moduleContentIndex = -1;
    content.forEach((item, idx) => {
        item.path = 'app/' + item.path.substring(demoFolder.length);
        if (item.path.match(/.+\.ts$/i)) {
            item.code = fixImport(item.code);
            item.code = fixTemplateUrl(item.code);
            item.code = fixStyleUrls(item.code);
            item.code = fixCodeForDemoOnly(item.code);
            findMockDatas(item.code).forEach(mockData => mockDatas.push(mockData));
        }
        if (item.path == 'app/app.component.ts') {
            compContentIndex = idx;
        } else if (item.path == 'app/app.module.ts') {
            moduleContentIndex = idx;
        }
    });
    if (compContentIndex == -1) {
        console.error('ERROR: need this file: ' + demoFolder + 'app.module.ts');
        process.exit(100);
    }
    if (moduleContentIndex == -1) {
        console.error('ERROR: need this file: ' + demoFolder + 'app.component.ts');
        process.exit(100);
    }

    var moduleItem = content[moduleContentIndex];
    moduleItem.code = fixAppModuleTs(moduleItem.code);
    var compItem = content[compContentIndex];
    compItem.code = fixAppComponentTs(compItem.code, moduleItem.code);

    mockDatas.forEach(mockData => content.push(mockData));

    content.push(getIndexHtml());
    content.push(getMainTs());
    content.push(getSystemJsConfig());
    content.push(getSystemJsAngularLoader());

    var html = '';
    content.forEach(item => {
        var path = item.path;
        item.code = escapeCode(item.code);
        html += `<input type="hidden" name="entries[${path}][encoding]" value="utf8" />\n`;
        html += `<input type="hidden" name="entries[${path}][content]" value="${item.code}" />\n`;
    });

    var plunker = template
        .replace('<!-- replace-by-content -->', html)
        .replace('<!-- replace-by-title -->', demoFolder.substring(demoHome.length, demoFolder.length-1));

    var saveTo = outputHome + demoFolder.substring(demoHome.length);
    makeDirs(saveTo);
    saveTo += 'index.html';
    fs.writeFileSync(saveTo, plunker);
    console.log('made plunker to ' + saveTo);
}

function readDemoContent(content, demoFolder) {
    var demoFiles = fs.readdirSync(demoFolder);
    demoFiles.forEach(demoFile => {
        var pathname = demoFolder + demoFile;
        var stat = fs.lstatSync(pathname);
        if (stat.isDirectory()) {
            readDemoContent(content, pathname + '/');
        } else {
            content.push({path: pathname, code: readCode(pathname)});
        }
    });
}

function fixTemplateUrl(code) {
    return code.replace(/\btemplateUrl\s*:\s*['"]\s*(.*?)\s*['"]/g, (found, templateUrl) => {
        if (templateUrl.substring(0, 2) !== './') {
            templateUrl = './' + templateUrl;
        }
        return 'templateUrl: "' + templateUrl + '"';
    });
}

function fixStyleUrls(code) {
    return code.replace(/\bstyleUrls\s*:\s*(\[[\s\S]*?\])/g, (found, urlString) => {
        var urls = eval(urlString);
        urls = urls.map(url => {
            if (url.substring(0, 2) !== './') {
                url = './' + url;
            }
            return url;
        });
        return 'styleUrls: ["' + urls.join('", "') + '"]';
    });
}

function fixImport(code) {
    var jigsawImports = [];
    var rawImports = [];
    while (true) {
        var match = code.match(/\bimport\s+\{([\s\S]+?)\}\s+from\s+['"](.+?)['"]/);
        if (!match) {
            break;
        }
        if (match[2].match(/jigsaw\/.+?/)) {
            var importString = match[1];
            var imports = importString.split(/,/g).map(item => item.trim());
            imports.forEach(item => jigsawImports.push(item));
        } else {
            rawImports.push(match[0]);
        }
        code = code.substring(match.index + match[0].length);
    }
    jigsawImports = jigsawImports.sort((a, b) => a.localeCompare(b));

    var jigsawImportString = '';
    if (jigsawImports.length > 0) {
        jigsawImportString = 'import {\n';
        for(var i = 0, len = jigsawImports.length; i < len; i += 3) {
           jigsawImportString += '    ' + jigsawImports.slice(i, i+3).join(', ') + ',\n';
        }
        jigsawImportString += '} from "@rdkmaster/jigsaw";';
    }

    return jigsawImportString + '\n' + rawImports.join(';\n') + code;
}

function fixCodeForDemoOnly(code) {
    return code.replace(/\/\* #for-live-demo-only#([\s\S]*?)\*\//g, (found, codeForDemo) => codeForDemo.trim());
}

function findMockDatas(code) {
    var ret = [];
    var match = code.match(/mock-data\/.*?['"]/g);
    if (!match) {
        return ret;
    }
    var map = {};
    match.forEach(path => {
        path = path.substring(0, path.length-1);
        map[path] = readCode(`${demoHome}/../../${path}`);
    });
    for (var path in map) {
        ret.push({path: path, code: map[path]})
    }
    return ret;
}

function fixAppComponentTs(compCode, moduleCode) {
    var match = moduleCode.match(/bootstrap\s*:\s*\[\s*(\w+?)\s*\]/);
    if (!match) {
        console.error('ERROR: need bootstrap property in the app.module.ts, the code is:\n' + moduleCode);
        process.exit(200);
    }

    var mainComp = match[1];
    return compCode.replace(/@Component\s*\(\s*\{([\s\S]*?)\}\s*\)[\s\S]*?export\s+class\s+(\w+?)\b/g,
        (found, props, className) => {
            if (className != mainComp) {
                return found;
            }
            if (found.match(/selector\s*:/)) {
                console.error('ERROR: more than one "selector" appears, remove the "selector" property, ' +
                    'the code is:\n' + found);
                process.exit(201);
            }
            return found.replace(/@Component\s*\(\s*\{/, '@Component({\n    selector: "jigsaw-live-demo",');
        });
}

function fixAppModuleTs(appModuleCode) {
    appModuleCode = "import {BrowserModule} from '@angular/platform-browser';\n" +
        "import {BrowserAnimationsModule} from '@angular/platform-browser/animations';\n" +
        "import {HttpModule} from '@angular/http';\n" +
        appModuleCode.replace(/export\s+class\s+(.+?)\s*{/, 'export class AppModule {');

    var re = /\bimports\s*:\s*\[([\s\S]*?)\]/;
    var match = appModuleCode.match(/\bimports\s*:\s*\[([\s\S]*?)\]/);
    if (match) {
        return appModuleCode.replace(re, (found, importString) => 'imports: [\n' +
            '        BrowserModule, BrowserAnimationsModule, HttpModule,\n' +
            '        ' + importString.trim() + '\n' +
            '    ]'
        );
    } else {
        return appModuleCode.replace('@NgModule({',
            '@NgModule({\nimports: [BrowserModule, BrowserAnimationsModule, HttpModule],');
    }

}

function escapeCode(code) {
    return code.replace(/</g, '<').replace(/>/g, '>')
               .replace(/"/g, '"').replace(/'/g, ''');
}

function makeDirs(path) {
    var pathPartials = path.split(/[\/\\]/g);
    for(var i = 1; i < pathPartials.length; i++) {
        var arr = pathPartials.slice(0, i);
        var p = arr.join('/');
        // p == '' if path is absolute
        if (fs.existsSync(p) || !p) {
            continue;
        }
        fs.mkdirSync(p, 755);
    }
}

function readCode(path) {
    return fs.readFileSync(path).toString();
}

function getDemoHome(dirName) {
    var pathPartials = __dirname.split(/[\/\\]/g);
    pathPartials.pop();
    pathPartials.pop();
    var demoHome = pathPartials.join('/') + '/src/app/'+ dirName + '/';
    return demoHome;
}

function getTemplate() {
    return fs.readFileSync(__dirname + '/demo-independent-templates/plunker.embed.template.html').toString();
}

function getIndexHtml() {
    return {
        path: 'index.html',
        code: readCode(__dirname + '/demo-independent-templates/index.html')
    }
}

function getMainTs() {
    return {
        path: 'main.ts',
        code: readCode(__dirname + '/demo-independent-templates/main.ts')
    }
}

function getSystemJsAngularLoader() {
    return {
        path: 'systemjs-angular-loader.js',
        code: readCode(__dirname + '/demo-independent-templates/systemjs-angular-loader.js')
    }
}

function getSystemJsConfig() {
    return {
        path: 'systemjs.config.js',
        code: readCode(__dirname + '/demo-independent-templates/systemjs.config.js')
    }
}
<commit_msg>live-demo build into one folder<commit_after>var fs = require('fs');
var template = getTemplate();
var demoHome = null;
var outputHome = process.argv.length > 2 ? process.argv[2] : './live-demo/';

if (fs.existsSync(outputHome)) {
    console.error("ERROR: remove output dir and try again: " + outputHome);
    process.exit(1);
}
outputHome = outputHome ? outputHome.trim() : './live-demo/';
var outputHomeRoot = outputHome.match(/[\/\\]$/) ? outputHome : outputHome + '/';

makeAllPlunkers('e2e-testee');
makeAllPlunkers('live-demo');

function makeAllPlunkers(dirName) {
    demoHome = getDemoHome(dirName);

    var demoSetFolders = fs.readdirSync(demoHome);
    demoSetFolders.forEach(demoFolder => {
        outputHome = outputHomeRoot;
        var pathname = demoHome + demoFolder;
        var stat = fs.lstatSync(pathname);
        if (stat.isDirectory()) {
            if(dirName == 'live-demo'){
                makePlunker(pathname + '/', dirName);
            } else if(dirName == 'e2e-testee') {
                processDemoSet(pathname + '/');
            }
        }
    });
}

function processDemoSet(demoSetFolder) {
    var demoFolders = fs.readdirSync(demoSetFolder);
    demoFolders.forEach(demoFolder => {
        var pathname = demoSetFolder + demoFolder;
        var stat = fs.lstatSync(pathname);
        if (stat.isDirectory()) {
            makePlunker(pathname + '/');
        }
    });
}

function makePlunker(demoFolder, dirName) {
    var content = [];
    var mockDatas = [];
    readDemoContent(content, demoFolder);
    var compContentIndex = -1;
    var moduleContentIndex = -1;
    content.forEach((item, idx) => {
        item.path = 'app/' + item.path.substring(demoFolder.length);
        if (item.path.match(/.+\.ts$/i)) {
            item.code = fixImport(item.code);
            item.code = fixTemplateUrl(item.code);
            item.code = fixStyleUrls(item.code);
            item.code = fixCodeForDemoOnly(item.code);
            findMockDatas(item.code).forEach(mockData => mockDatas.push(mockData));
        }
        if (item.path == 'app/app.component.ts') {
            compContentIndex = idx;
        } else if (item.path == 'app/app.module.ts') {
            moduleContentIndex = idx;
        }
    });
    if (compContentIndex == -1) {
        console.error('ERROR: need this file: ' + demoFolder + 'app.module.ts');
        process.exit(100);
    }
    if (moduleContentIndex == -1) {
        console.error('ERROR: need this file: ' + demoFolder + 'app.component.ts');
        process.exit(100);
    }

    var moduleItem = content[moduleContentIndex];
    moduleItem.code = fixAppModuleTs(moduleItem.code);
    var compItem = content[compContentIndex];
    compItem.code = fixAppComponentTs(compItem.code, moduleItem.code);

    mockDatas.forEach(mockData => content.push(mockData));

    content.push(getIndexHtml());
    content.push(getMainTs());
    content.push(getSystemJsConfig());
    content.push(getSystemJsAngularLoader());

    var html = '';
    content.forEach(item => {
        var path = item.path;
        item.code = escapeCode(item.code);
        html += `<input type="hidden" name="entries[${path}][encoding]" value="utf8" />\n`;
        html += `<input type="hidden" name="entries[${path}][content]" value="${item.code}" />\n`;
    });

    var plunker = template
        .replace('<!-- replace-by-content -->', html)
        .replace('<!-- replace-by-title -->', demoFolder.substring(demoHome.length, demoFolder.length-1));

    var saveTo = outputHome + demoFolder.substring(demoHome.length) + (dirName ? dirName + '/' : '');
    console.log(saveTo);
    makeDirs(saveTo);
    saveTo += 'index.html';
    fs.writeFileSync(saveTo, plunker);
    console.log('made plunker to ' + saveTo);
}

function readDemoContent(content, demoFolder) {
    var demoFiles = fs.readdirSync(demoFolder);
    demoFiles.forEach(demoFile => {
        var pathname = demoFolder + demoFile;
        var stat = fs.lstatSync(pathname);
        if (stat.isDirectory()) {
            readDemoContent(content, pathname + '/');
        } else {
            content.push({path: pathname, code: readCode(pathname)});
        }
    });
}

function fixTemplateUrl(code) {
    return code.replace(/\btemplateUrl\s*:\s*['"]\s*(.*?)\s*['"]/g, (found, templateUrl) => {
        if (templateUrl.substring(0, 2) !== './') {
            templateUrl = './' + templateUrl;
        }
        return 'templateUrl: "' + templateUrl + '"';
    });
}

function fixStyleUrls(code) {
    return code.replace(/\bstyleUrls\s*:\s*(\[[\s\S]*?\])/g, (found, urlString) => {
        var urls = eval(urlString);
        urls = urls.map(url => {
            if (url.substring(0, 2) !== './') {
                url = './' + url;
            }
            return url;
        });
        return 'styleUrls: ["' + urls.join('", "') + '"]';
    });
}

function fixImport(code) {
    var jigsawImports = [];
    var rawImports = [];
    while (true) {
        var match = code.match(/\bimport\s+\{([\s\S]+?)\}\s+from\s+['"](.+?)['"]/);
        if (!match) {
            break;
        }
        if (match[2].match(/jigsaw\/.+?/)) {
            var importString = match[1];
            var imports = importString.split(/,/g).map(item => item.trim());
            imports.forEach(item => jigsawImports.push(item));
        } else {
            rawImports.push(match[0]);
        }
        code = code.substring(match.index + match[0].length);
    }
    jigsawImports = jigsawImports.sort((a, b) => a.localeCompare(b));

    var jigsawImportString = '';
    if (jigsawImports.length > 0) {
        jigsawImportString = 'import {\n';
        for(var i = 0, len = jigsawImports.length; i < len; i += 3) {
           jigsawImportString += '    ' + jigsawImports.slice(i, i+3).join(', ') + ',\n';
        }
        jigsawImportString += '} from "@rdkmaster/jigsaw";';
    }

    return jigsawImportString + '\n' + rawImports.join(';\n') + code;
}

function fixCodeForDemoOnly(code) {
    return code.replace(/\/\* #for-live-demo-only#([\s\S]*?)\*\//g, (found, codeForDemo) => codeForDemo.trim());
}

function findMockDatas(code) {
    var ret = [];
    var match = code.match(/mock-data\/.*?['"]/g);
    if (!match) {
        return ret;
    }
    var map = {};
    match.forEach(path => {
        path = path.substring(0, path.length-1);
        map[path] = readCode(`${demoHome}/../../${path}`);
    });
    for (var path in map) {
        ret.push({path: path, code: map[path]})
    }
    return ret;
}

function fixAppComponentTs(compCode, moduleCode) {
    var match = moduleCode.match(/bootstrap\s*:\s*\[\s*(\w+?)\s*\]/);
    if (!match) {
        console.error('ERROR: need bootstrap property in the app.module.ts, the code is:\n' + moduleCode);
        process.exit(200);
    }

    var mainComp = match[1];
    return compCode.replace(/@Component\s*\(\s*\{([\s\S]*?)\}\s*\)[\s\S]*?export\s+class\s+(\w+?)\b/g,
        (found, props, className) => {
            if (className != mainComp) {
                return found;
            }
            if (found.match(/selector\s*:/)) {
                console.error('ERROR: more than one "selector" appears, remove the "selector" property, ' +
                    'the code is:\n' + found);
                process.exit(201);
            }
            return found.replace(/@Component\s*\(\s*\{/, '@Component({\n    selector: "jigsaw-live-demo",');
        });
}

function fixAppModuleTs(appModuleCode) {
    appModuleCode = "import {BrowserModule} from '@angular/platform-browser';\n" +
        "import {BrowserAnimationsModule} from '@angular/platform-browser/animations';\n" +
        "import {HttpModule} from '@angular/http';\n" +
        appModuleCode.replace(/export\s+class\s+(.+?)\s*{/, 'export class AppModule {');

    var re = /\bimports\s*:\s*\[([\s\S]*?)\]/;
    var match = appModuleCode.match(/\bimports\s*:\s*\[([\s\S]*?)\]/);
    if (match) {
        return appModuleCode.replace(re, (found, importString) => 'imports: [\n' +
            '        BrowserModule, BrowserAnimationsModule, HttpModule,\n' +
            '        ' + importString.trim() + '\n' +
            '    ]'
        );
    } else {
        return appModuleCode.replace('@NgModule({',
            '@NgModule({\nimports: [BrowserModule, BrowserAnimationsModule, HttpModule],');
    }

}

function escapeCode(code) {
    return code.replace(/</g, '<').replace(/>/g, '>')
               .replace(/"/g, '"').replace(/'/g, ''');
}

function makeDirs(path) {
    var pathPartials = path.split(/[\/\\]/g);
    for(var i = 1; i < pathPartials.length; i++) {
        var arr = pathPartials.slice(0, i);
        var p = arr.join('/');
        // p == '' if path is absolute
        if (fs.existsSync(p) || !p) {
            continue;
        }
        fs.mkdirSync(p, 755);
    }
}

function readCode(path) {
    return fs.readFileSync(path).toString();
}

function getDemoHome(dirName) {
    var pathPartials = __dirname.split(/[\/\\]/g);
    pathPartials.pop();
    pathPartials.pop();
    var demoHome = pathPartials.join('/') + '/src/app/'+ dirName + '/';
    return demoHome;
}

function getTemplate() {
    return fs.readFileSync(__dirname + '/demo-independent-templates/plunker.embed.template.html').toString();
}

function getIndexHtml() {
    return {
        path: 'index.html',
        code: readCode(__dirname + '/demo-independent-templates/index.html')
    }
}

function getMainTs() {
    return {
        path: 'main.ts',
        code: readCode(__dirname + '/demo-independent-templates/main.ts')
    }
}

function getSystemJsAngularLoader() {
    return {
        path: 'systemjs-angular-loader.js',
        code: readCode(__dirname + '/demo-independent-templates/systemjs-angular-loader.js')
    }
}

function getSystemJsConfig() {
    return {
        path: 'systemjs.config.js',
        code: readCode(__dirname + '/demo-independent-templates/systemjs.config.js')
    }
}
<|endoftext|>


<commit_before>module.exports = {
  'zh-CN': [
    {
      name: '开发指南',
      groups: [
        {
          groupName: '使用',
          list: [
            {
              title: '快速上手',
              path: 'guides/install',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/README_zh-CN.md') })",
            },
            {
              title: '国际化',
              path: 'guides/i18n',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/I18N_zh-CN.md') })",
            },
            {
              title: 'API文档',
              link: 'apidoc',
            },
            {
              title: 'babel-plugin-zent',
              path: 'guides/babel-plugin-zent',
              hidden: true,
              source:
                "DocLoadable({ loader: () => import('../../packages/babel-plugin-zent/README_zh-CN.md') })",
            },
          ],
        },
        {
          groupName: '主题',
          list: [
            // {
            //   title: '色彩',
            //   path: 'guides/colors',
            //   source:
            //     "DocLoadable({ loader: () => import('./pages/colors/zh-CN.js') })",
            // },
            {
              title: '定制主题',
              path: 'guides/theme',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/THEME_zh-CN.md') })",
            },
          ],
        },
        {
          groupName: '升级',
          list: [
            {
              title: '更新日志',
              path: 'guides/changelog',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/RELEASE_zh-CN.md') })",
            },
            {
              title: '7.0.0 迁移指南',
              path: 'guides/changelog-v7',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/RELEASE_v7.md') })",
            },
            {
              title: '3.x 升级指南',
              path: 'migrating/3x',
              hidden: true,
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/migrating-2-3_zh-CN.md') })",
            },
            {
              title: '2.1.x 升级指南',
              path: 'migrating/21x',
              hidden: true,
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/migrating-2.1_zh-CN.md') })",
            },
            {
              title: 'Github 日志',
              path: 'guides/github_changelog',
              hidden: true,
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/CHANGELOG.md') })",
            },
          ],
        },
        {
          groupName: '开发',
          list: [
            {
              title: '如何参与',
              path: 'guides/contribute',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/CONTRIBUTING_zh-CN.md') })",
            },
            {
              title: '文档规范',
              path: 'guides/markdown',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/MARKDOWN_zh-CN.md') })",
            },
          ],
        },
      ],
    },
    {
      name: '组件',
      groups: [],
    },
  ],

  'en-US': [
    {
      name: 'Guides',
      groups: [
        {
          groupName: 'Usage',
          list: [
            {
              title: 'Quick Start',
              path: 'guides/install',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/README_en-US.md') })",
            },
            {
              title: 'Internationalization',
              path: 'guides/i18n',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/I18N_en-US.md') })",
            },
            {
              title: 'API Document',
              link: 'apidoc',
            },
            {
              title: 'babel-plugin-zent',
              path: 'guides/babel-plugin-zent',
              hidden: true,
              source:
                "DocLoadable({ loader: () => import('../../packages/babel-plugin-zent/README_en-US.md') })",
            },
          ],
        },
        {
          groupName: 'Theme',
          list: [
            // {
            //   title: 'Colors',
            //   path: 'guides/colors',
            //   source:
            //     "DocLoadable({ loader: () => import('./pages/colors/en-US.js') })",
            // },
            {
              title: 'Customize',
              path: 'guides/theme',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/THEME_en-US.md') })",
            },
          ],
        },
        {
          groupName: 'Releases',
          list: [
            {
              title: 'Change Log',
              path: 'guides/changelog',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/RELEASE_en-US.md') })",
            },
            {
              title: 'Upgrade to 7.0.0',
              path: 'guides/changelog-v7',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/RELEASE_v7.md') })",
            },
            {
              title: 'Upgrade to 3.x',
              path: 'migrating/3x',
              hidden: true,
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/migrating-2-3_en-US.md') })",
            },
            {
              title: 'Upgrade to 2.1.x',
              path: 'migrating/21x',
              hidden: true,
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/migrating-2.1_en-US.md') })",
            },
            {
              title: 'Github Log',
              path: 'guides/github_changelog',
              hidden: true,
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/CHANGELOG.md') })",
            },
          ],
        },
        {
          groupName: 'Contributing',
          list: [
            {
              title: 'How To',
              path: 'guides/contribute',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/CONTRIBUTING_en-US.md') })",
            },
            {
              title: 'Writing Docs',
              path: 'guides/markdown',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/MARKDOWN_en-US.md') })",
            },
          ],
        },
      ],
    },
    {
      name: 'Components',
      groups: [],
    },
  ],
};
<commit_msg>Expose babel plugin in nav (#1421)<commit_after>module.exports = {
  'zh-CN': [
    {
      name: '开发指南',
      groups: [
        {
          groupName: '使用',
          list: [
            {
              title: '快速上手',
              path: 'guides/install',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/README_zh-CN.md') })",
            },
            {
              title: 'Babel 插件',
              path: 'guides/babel-plugin-zent',
              source:
                "DocLoadable({ loader: () => import('../../packages/babel-plugin-zent/README_zh-CN.md') })",
            },
            {
              title: '国际化',
              path: 'guides/i18n',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/I18N_zh-CN.md') })",
            },
            {
              title: 'API文档',
              link: 'apidoc',
            },
          ],
        },
        {
          groupName: '主题',
          list: [
            // {
            //   title: '色彩',
            //   path: 'guides/colors',
            //   source:
            //     "DocLoadable({ loader: () => import('./pages/colors/zh-CN.js') })",
            // },
            {
              title: '定制主题',
              path: 'guides/theme',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/THEME_zh-CN.md') })",
            },
          ],
        },
        {
          groupName: '升级',
          list: [
            {
              title: '更新日志',
              path: 'guides/changelog',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/RELEASE_zh-CN.md') })",
            },
            {
              title: '7.0.0 迁移指南',
              path: 'guides/changelog-v7',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/RELEASE_v7.md') })",
            },
            {
              title: '3.x 升级指南',
              path: 'migrating/3x',
              hidden: true,
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/migrating-2-3_zh-CN.md') })",
            },
            {
              title: '2.1.x 升级指南',
              path: 'migrating/21x',
              hidden: true,
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/migrating-2.1_zh-CN.md') })",
            },
            {
              title: 'Github 日志',
              path: 'guides/github_changelog',
              hidden: true,
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/CHANGELOG.md') })",
            },
          ],
        },
        {
          groupName: '开发',
          list: [
            {
              title: '如何参与',
              path: 'guides/contribute',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/CONTRIBUTING_zh-CN.md') })",
            },
            {
              title: '文档规范',
              path: 'guides/markdown',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/MARKDOWN_zh-CN.md') })",
            },
          ],
        },
      ],
    },
    {
      name: '组件',
      groups: [],
    },
  ],

  'en-US': [
    {
      name: 'Guides',
      groups: [
        {
          groupName: 'Usage',
          list: [
            {
              title: 'Quick Start',
              path: 'guides/install',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/README_en-US.md') })",
            },
            {
              title: 'Babel Plugin',
              path: 'guides/babel-plugin-zent',
              source:
                "DocLoadable({ loader: () => import('../../packages/babel-plugin-zent/README_en-US.md') })",
            },
            {
              title: 'Internationalization',
              path: 'guides/i18n',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/I18N_en-US.md') })",
            },
            {
              title: 'API Document',
              link: 'apidoc',
            },
          ],
        },
        {
          groupName: 'Theme',
          list: [
            // {
            //   title: 'Colors',
            //   path: 'guides/colors',
            //   source:
            //     "DocLoadable({ loader: () => import('./pages/colors/en-US.js') })",
            // },
            {
              title: 'Customize',
              path: 'guides/theme',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/THEME_en-US.md') })",
            },
          ],
        },
        {
          groupName: 'Releases',
          list: [
            {
              title: 'Change Log',
              path: 'guides/changelog',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/RELEASE_en-US.md') })",
            },
            {
              title: 'Upgrade to 7.0.0',
              path: 'guides/changelog-v7',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/RELEASE_v7.md') })",
            },
            {
              title: 'Upgrade to 3.x',
              path: 'migrating/3x',
              hidden: true,
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/migrating-2-3_en-US.md') })",
            },
            {
              title: 'Upgrade to 2.1.x',
              path: 'migrating/21x',
              hidden: true,
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/migrating-2.1_en-US.md') })",
            },
            {
              title: 'Github Log',
              path: 'guides/github_changelog',
              hidden: true,
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/CHANGELOG.md') })",
            },
          ],
        },
        {
          groupName: 'Contributing',
          list: [
            {
              title: 'How To',
              path: 'guides/contribute',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/CONTRIBUTING_en-US.md') })",
            },
            {
              title: 'Writing Docs',
              path: 'guides/markdown',
              source:
                "DocLoadable({ loader: () => import('../../packages/zent/docs/MARKDOWN_en-US.md') })",
            },
          ],
        },
      ],
    },
    {
      name: 'Components',
      groups: [],
    },
  ],
};
<|endoftext|>


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

// Usage instructions: Create a single array variable named 'activity'. This
// represents explanatory text and one or more questions to present to the
// student. Each element in the array should itself be either
//
// -- a string containing a set of complete HTML elements. That is, if the
//    string contains an open HTML tag (such as <form>), it must also have the
//    corresponding close tag (such as </form>). You put the actual question
//    text in a string.
//
// -- a JavaScript object representing the answer information for a question.
//    That is, the object contains properties such as the type of question, a
//    regular expression indicating the correct answer, a string to show in
//    case of either correct or incorrect answers or to show when the student
//    asks for help. For more information on how to specify the object, please
//    see http://code.google.com/p/course-builder/wiki/CreateActivities.

var activity = [

  '

Search Tips:

When you do certain queries, Google presents information about these topics directly on the search results page.
You can distinguish the information in these panels from advertisements because advertisements are labeled as Ads. Also, when these panels appear, they are always the top box on the right-hand side.
Topics for which information panels appear include, but are not limited to, animals, famous people, landmarks, countries, movies, books, works of art, sports teams, and chemical elements.

',

  'Have you ever played the "Six Degrees of Separation" game, where you try to get from one celebrity to another via co-stars in movies they have in common? Clicking only in the information panels on the right side of the screen, our search expert got from Mona Lisa to the Golden Gate Bridge in seven clicks. That is, she entered the query [Mona Lisa], clicked on something in the panel on the right side of the screen, then clicked on something else in the resulting screen, and so forth, and finally ended up at a page about the Golden Gate Bridge. How did she do it? Can you do it with fewer clicks?
Find your own "six degrees" chain using the panels on the right. Share your story in the forum.',

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

// Usage instructions: Create a single array variable named 'activity'. This
// represents explanatory text and one or more questions to present to the
// student. Each element in the array should itself be either
//
// -- a string containing a set of complete HTML elements. That is, if the
//    string contains an open HTML tag (such as <form>), it must also have the
//    corresponding close tag (such as </form>). You put the actual question
//    text in a string.
//
// -- a JavaScript object representing the answer information for a question.
//    That is, the object contains properties such as the type of question, a
//    regular expression indicating the correct answer, a string to show in
//    case of either correct or incorrect answers or to show when the student
//    asks for help. For more information on how to specify the object, please
//    see http://code.google.com/p/course-builder/wiki/CreateActivities.

var activity = [

  'Go to Liquibase Download page and download liquibase to your local system. Then,
'
    + '
Uncompress it locally

Add Liquibase CLI to your path

',

  '',

];
<|endoftext|>


<commit_before>// NPM Libraries
import { hot } from "react-hot-loader";
import { Meteor } from "meteor/meteor";
import React, { Component, Fragment } from "react";
import { Router, Route, Redirect } from "react-router-dom";
import history from "../utils/history";
import qs from "query-string";

// Includes/Fragments
import MainMenu from "./includes/MainMenu";

// Pages
import Home from "./pages/Home";
import Whitepaper from "./pages/WhitePaper";
import Team from "./pages/TeamMembers";
import Faq from "./pages/Faq";
import Partners from "./pages/Partners";
import About from "./pages/About";
import Map_ from "./pages/Map";
import NewEventLoadable from "./pages/NewEvent/loadable";
import CongratsModal from "./pages/NewEvent/CongratsModal";
import Page from "./pages/Page";
import { Error404 } from "./pages/Errors";

import WPIntro from "./pages/WhitePaper/Intro";
import WPWhy from "./pages/WhitePaper/Why";
import WPFAQs from "./pages/WhitePaper/faqs";

// Components
import ScrollToTop from "./components/ScrollToTop";
import Admin from "./pages/Admin/index"

// Docuss
import { comToPlugin, inIFrame } from 'dcs-client'
import { SimpleRouteMatcher } from 'meteor/sylque:dcs-simple-route-matcher'
import { runReactRouterSync } from 'dcs-react-router-sync'
import websiteJSON from '../../../public/dcs-website.json'

// Styles and Other
import './styles.scss'

//------------------------------------------------------------------------------

class App extends Component {
  componentDidMount() {
    // Add the touch-screen flag to the <html> tag
    const touchScreen =
      !!("ontouchstart" in window) || window.navigator.msMaxTouchPoints > 0;
    if (touchScreen) {
      document.documentElement.classList.add("touch-screen");
    }

    setTimeout(() => {
      document.querySelector("#root").classList.toggle("show");
    }, 100); // add a fading effect on the inital loading
  }

  render() {

    const routePaths = {
      root: "/",
      home: "/home",
      team: "/team",
      partners: "/partners",
      whitepaper: "/whitepaper",
      faq: "/faq",
      about: "/about",
      map: "/map",
      admin: "/admin",
      thankyou: "/thank-you",
      page: "/page",
      signin: "/sign-in",
      signup: "/sign-up",
      change_password: "/change-password",
      forgot_password: "/forgot-password",
      sso_auth: "/sso_auth",

      whitepaper_intro: "/whitepaper/intro",
      whitepaper_why: "/whitepaper/why",
      whitepaper_faqs: "/whitepaper/faqs"
    }
    const standaloneMode = !inIFrame()

    return (
      <Router history={history}>
        <Fragment>
          {standaloneMode && <MainMenu />}
                    <ScrollToTop>
            <Route exact path={routePaths.root} component={Home} />
            <Route exact path={routePaths.home} component={Home} />
            <Route exact path={routePaths.team} component={Team} />
            <Route exact path={routePaths.partners} component={Partners} />
            <Route exact path={routePaths.whitepaper} component={Whitepaper} />
            <Route exact path={routePaths.faq} component={Faq} />
            <Route exact path={routePaths.about} component={About} />
            <Route path={routePaths.map} component={Map_} />
            <Route exact path={routePaths.admin} render={props => <Admin {...props} />} />
            <Route exact path={routePaths.thankyou} component={CongratsModal} />
            <Route exact path={`${routePaths.page}/:id`} component={Page} />

            <Route exact path={routePaths.whitepaper_intro} component={WPIntro} />
            <Route exact path={routePaths.whitepaper_why} render={WPWhy} />
            <Route exact path={routePaths.whitepaper_faqs} render={WPFAQs} />

            <Route path="*" render={() => this.check404Route(Object.values(routePaths))} />
          </ScrollToTop>
        </Fragment>
      </Router>
    );
  }

  renderNewEvent = ({ location, history }) => {
    const { new: new_, edit } = qs.parse(location.search);
    const isOpen = Boolean(new_ === "1" || (edit === "1" && window.__editData));

    if (isOpen && !Meteor.userId()) {
      /*
      sessionStorage.setItem("redirect", "/?new=1");
      return <Redirect to="/sign-in" />;
      */
      alert('You need to login before you can create an event')
      return null
    }
    /*
    else if(!isOpen){
      return <Redirect to='/home' />
    }
    */
    console.log('passed in loc:\n', location)
    console.log('passed in hist:\n', history)
    return (
      <NewEventLoadable isOpen={isOpen} location={location} history={history} />
    );
  };

  /**
   * This function manages the 'catch-all' route, serving two purposes.
   * (1) open a model to create/edit event when there is the appropriate search string in the URL
   * (2) for all other routes not specified, it will redirect to a 404 page
   * Ideally we should be using React-router Switch to create a fallback 404 page...
   * But this would require opening the new event modal without using the URL as a hook
   * And this may break interactions with Docus (e.g. editing an event directly from the forum)
   */
  check404Route = (routes) => {
    if (window.location.search === '?new=1' || window.location.search === '?edit=1') {
      return this.renderNewEvent({ location: window.location, history })
    }
    if (!routes.some(e => e === window.location.pathname)
      && !window.location.pathname.includes('/page/')
      && !window.location.pathname.includes('reset-password')) {
        return <Error404 />
    }
    return null
  }
}

export default hot(module)(App);

//------------------------------------------------------------------------------

// Docuss

if (inIFrame()) {
  comToPlugin.connect({
    discourseOrigin: '*',
    timeout: 10000,
    onTimeout: () => console.log('Could not connect to the Docuss plugin')
  })

  // Set Docuss-generated topic to have pre-populated category
  comToPlugin.onDiscourseRoutePushed(({ route }) => {
    const topicCategory =
      route.pageName === 'm_about'? 'The About Page Discussion' :
      route.pageName === 'whitepaper'? 'Public Happiness Token' :
      route.pageName === 'wp_why'? 'Public Happiness Token' :
      route.pageName === 'wp_intro'? 'Public Happiness Token' :
      route.pageName === 'wp_faqs'? 'Public Happiness Token' :
      route.pageName === 'm_gather'? 'Hidden' :
   // route.pageName === 'summit'? 'The Happier World Economies Summit' :
      'General Discussion'
    comToPlugin.postSetRouteProps({ category: topicCategory })
  })

}

export const routeMatcher = new SimpleRouteMatcher({
  maxPageNameLength: websiteJSON.dcsTag.maxPageNameLength,
  forceLowercase: websiteJSON.dcsTag.forceLowercase,
  predefinedPageNames: websiteJSON.pages.map(p => ({
    pageName: p.name,
    pathname: p.url // This works because we know our urls are all relative urls, i.e. pathname = url
  })),
  otherPagesPrefix: websiteJSON.webApp.otherPagesPrefix
})

runReactRouterSync({ browserHistory: history, routeMatcher })

//------------------------------------------------------------------------------
<commit_msg>removing unused category<commit_after>// NPM Libraries
import { hot } from "react-hot-loader";
import { Meteor } from "meteor/meteor";
import React, { Component, Fragment } from "react";
import { Router, Route, Redirect } from "react-router-dom";
import history from "../utils/history";
import qs from "query-string";

// Includes/Fragments
import MainMenu from "./includes/MainMenu";

// Pages
import Home from "./pages/Home";
import Whitepaper from "./pages/WhitePaper";
import Team from "./pages/TeamMembers";
import Faq from "./pages/Faq";
import Partners from "./pages/Partners";
import About from "./pages/About";
import Map_ from "./pages/Map";
import NewEventLoadable from "./pages/NewEvent/loadable";
import CongratsModal from "./pages/NewEvent/CongratsModal";
import Page from "./pages/Page";
import { Error404 } from "./pages/Errors";

import WPIntro from "./pages/WhitePaper/Intro";
import WPWhy from "./pages/WhitePaper/Why";
import WPFAQs from "./pages/WhitePaper/faqs";

// Components
import ScrollToTop from "./components/ScrollToTop";
import Admin from "./pages/Admin/index"

// Docuss
import { comToPlugin, inIFrame } from 'dcs-client'
import { SimpleRouteMatcher } from 'meteor/sylque:dcs-simple-route-matcher'
import { runReactRouterSync } from 'dcs-react-router-sync'
import websiteJSON from '../../../public/dcs-website.json'

// Styles and Other
import './styles.scss'

//------------------------------------------------------------------------------

class App extends Component {
  componentDidMount() {
    // Add the touch-screen flag to the <html> tag
    const touchScreen =
      !!("ontouchstart" in window) || window.navigator.msMaxTouchPoints > 0;
    if (touchScreen) {
      document.documentElement.classList.add("touch-screen");
    }

    setTimeout(() => {
      document.querySelector("#root").classList.toggle("show");
    }, 100); // add a fading effect on the inital loading
  }

  render() {

    const routePaths = {
      root: "/",
      home: "/home",
      team: "/team",
      partners: "/partners",
      whitepaper: "/whitepaper",
      faq: "/faq",
      about: "/about",
      map: "/map",
      admin: "/admin",
      thankyou: "/thank-you",
      page: "/page",
      signin: "/sign-in",
      signup: "/sign-up",
      change_password: "/change-password",
      forgot_password: "/forgot-password",
      sso_auth: "/sso_auth",

      whitepaper_intro: "/whitepaper/intro",
      whitepaper_why: "/whitepaper/why",
      whitepaper_faqs: "/whitepaper/faqs"
    }
    const standaloneMode = !inIFrame()

    return (
      <Router history={history}>
        <Fragment>
          {standaloneMode && <MainMenu />}
                    <ScrollToTop>
            <Route exact path={routePaths.root} component={Home} />
            <Route exact path={routePaths.home} component={Home} />
            <Route exact path={routePaths.team} component={Team} />
            <Route exact path={routePaths.partners} component={Partners} />
            <Route exact path={routePaths.whitepaper} component={Whitepaper} />
            <Route exact path={routePaths.faq} component={Faq} />
            <Route exact path={routePaths.about} component={About} />
            <Route path={routePaths.map} component={Map_} />
            <Route exact path={routePaths.admin} render={props => <Admin {...props} />} />
            <Route exact path={routePaths.thankyou} component={CongratsModal} />
            <Route exact path={`${routePaths.page}/:id`} component={Page} />

            <Route exact path={routePaths.whitepaper_intro} component={WPIntro} />
            <Route exact path={routePaths.whitepaper_why} render={WPWhy} />
            <Route exact path={routePaths.whitepaper_faqs} render={WPFAQs} />

            <Route path="*" render={() => this.check404Route(Object.values(routePaths))} />
          </ScrollToTop>
        </Fragment>
      </Router>
    );
  }

  renderNewEvent = ({ location, history }) => {
    const { new: new_, edit } = qs.parse(location.search);
    const isOpen = Boolean(new_ === "1" || (edit === "1" && window.__editData));

    if (isOpen && !Meteor.userId()) {
      /*
      sessionStorage.setItem("redirect", "/?new=1");
      return <Redirect to="/sign-in" />;
      */
      alert('You need to login before you can create an event')
      return null
    }
    /*
    else if(!isOpen){
      return <Redirect to='/home' />
    }
    */
    console.log('passed in loc:\n', location)
    console.log('passed in hist:\n', history)
    return (
      <NewEventLoadable isOpen={isOpen} location={location} history={history} />
    );
  };

  /**
   * This function manages the 'catch-all' route, serving two purposes.
   * (1) open a model to create/edit event when there is the appropriate search string in the URL
   * (2) for all other routes not specified, it will redirect to a 404 page
   * Ideally we should be using React-router Switch to create a fallback 404 page...
   * But this would require opening the new event modal without using the URL as a hook
   * And this may break interactions with Docus (e.g. editing an event directly from the forum)
   */
  check404Route = (routes) => {
    if (window.location.search === '?new=1' || window.location.search === '?edit=1') {
      return this.renderNewEvent({ location: window.location, history })
    }
    if (!routes.some(e => e === window.location.pathname)
      && !window.location.pathname.includes('/page/')
      && !window.location.pathname.includes('reset-password')) {
        return <Error404 />
    }
    return null
  }
}

export default hot(module)(App);

//------------------------------------------------------------------------------

// Docuss

if (inIFrame()) {
  comToPlugin.connect({
    discourseOrigin: '*',
    timeout: 10000,
    onTimeout: () => console.log('Could not connect to the Docuss plugin')
  })

  // Set Docuss-generated topic to have pre-populated category
  comToPlugin.onDiscourseRoutePushed(({ route }) => {
    const topicCategory =
      route.pageName === 'm_about'? 'The About Page Discussion' :
      route.pageName === 'whitepaper'? 'Public Happiness Token' :
      route.pageName === 'wp_why'? 'Public Happiness Token' :
      route.pageName === 'wp_intro'? 'Public Happiness Token' :
      route.pageName === 'wp_faqs'? 'Public Happiness Token' :
      route.pageName === 'm_gather'? 'Hidden'
    comToPlugin.postSetRouteProps({ category: topicCategory })
  })

}

export const routeMatcher = new SimpleRouteMatcher({
  maxPageNameLength: websiteJSON.dcsTag.maxPageNameLength,
  forceLowercase: websiteJSON.dcsTag.forceLowercase,
  predefinedPageNames: websiteJSON.pages.map(p => ({
    pageName: p.name,
    pathname: p.url // This works because we know our urls are all relative urls, i.e. pathname = url
  })),
  otherPagesPrefix: websiteJSON.webApp.otherPagesPrefix
})

runReactRouterSync({ browserHistory: history, routeMatcher })

//------------------------------------------------------------------------------
<|endoftext|>