<commit_before>var Console = (function(IO) {
  var io,
      id;

  function init() {
    $('#console-input').on('keypress', 13, function(e) {
      if(e.keyCode === 13) {;
        consoleCommand($('#console-input').val());
        $('#console-input').val('');
        return false;
      }
    });

    io.on('log', function(req) {
      console.log(req);
    });
  }

  function listen(listenId) {
    id = listenId;
    io = IO.connect();
    io.emit('console-connect', {id: id});
  }

  function consoleCommand(cmd) {
    if(cmd.indexOf(':listen ') === 0) {
      listen(cmd.split(' ')[1]);
    } else if(cmd.indexOf(':clear') === 0) {
      $('#console-lines').html('');
      console.clear();
    } else {
      io.emit('command', {id: id, command: cmd});
    }
  }

  function printArgs() {
    $('#console-lines').prepend("

");
    var node;

    if(arguments.length === 1) {
      node = new PrettyJSON.view.Node({
        el:$('.console-line:first-of-type'),
          data:arguments[0]
      });
    } else {
      node = new PrettyJSON.view.Node({
        el:$('.console-line:first-of-type'),
        data:arguments
      });
    }
  }

  return {
    init: init
  };
})(io);
<commit_msg>Added some logging to the console.<commit_after>var Console = (function(IO) {
  var io,
      id,
      inputBuffer = [];

  function init() {
    $('#console-input').on('keypress', 13, function(e) {
      if(e.keyCode === 13) {;
        consoleCommand($('#console-input').val());
        $('#console-input').val('');
        return false;
      }
    });
  }

  function listen(listenId) {
    id = listenId;
    io = IO.connect();

    io.emit('console-connect', {id: id}, function(res) {
      printArgs("to your target application.");
      printArgs("Console attached, please add ");

      io.on('log', function(req) {
        printArgs(req.data.log);
      });
    });
  }

  function consoleCommand(cmd) {
    inputBuffer.unshift(cmd);

    if(cmd.indexOf(':listen ') === 0) {
      listen(cmd.split(' ')[1]);
    } else if(cmd.indexOf(':clear') === 0) {
      $('#console-lines').html('');
      console.clear();
    } else if (cmd.indexOf(':log') === 0) {
      var logStatement = cmd.split(' ').splice(1).join(' ');
      var res = eval("res = " + logStatement);

      console.log(res);
      printArgs(res);
    } else {
      io.emit('command', {id: id, command: cmd});
    }
  }

  function printArgs() {
    $('#console-lines').prepend("

");
    var node;

    if(arguments.length === 1) {
      node = new PrettyJSON.view.Node({
        el:$('.console-line:first-of-type'),
          data:arguments[0]
      });
    } else {
      node = new PrettyJSON.view.Node({
        el:$('.console-line:first-of-type'),
        data:arguments
      });
    }
  }

  return {
    init: init
  };
})(io);
<|endoftext|>


<commit_before>apos.widgetPlayers.facebook = function($el) {
  // N.B. Even though this is a player, it's not getting refreshed
  // once it's been created. Hrmmm.

  var data = apos.getWidgetData($el),
      pageUrl = data.pageUrl;

  $.getJSON(
    '/apos-facebook/feed',
    {
      limit: (data.limit || 5),
      pageUrl: pageUrl,
    },
    function(posts) {

      //Define our posts object as well as the template and loader.
      var $posts = $el.find('[data-apos-facebook-posts]'),
          $postTemplate = $posts.find('[data-apos-facebook-post].apos-template'),
          $loader = $posts.find('[data-apos-facebook-loader]');

      if (!posts.length) {
        $el.trigger('aposFacebookNull');
        return;
      }

      function init(){
        removePlaceholder();
        generatePostMarkup(posts);
      }

      function removePlaceholder(){
        $posts.find('[data-apos-facebook-placeholder]').remove();
      }

      function removeTemplate(){
        $postTemplate.remove();
      };

      function buildTemplate($template){
        $template.$title = $template.find('[data-apos-facebook-title]');
        $template.$link = $template.find('[data-apos-facebook-link]');
        $template.$date = $template.find('[data-apos-facebook-date]');
        $template.$photo = $template.find('[data-apos-facebook-photo]');
        $template.$body = $template.find('[data-apos-facebook-body]');
        return $template;
      }

      function cloneTemplate($obj){
        $clone = $obj.clone();
        $clone.removeClass('apos-template');
        clone = buildTemplate($clone);
        return clone;
      }

      function getImageUrl(postId, callback){
        var id = postId;
        $.getJSON(
          '/apos-facebook/photo',
          { id: id},
          function(response) {
            return callback(response);
          }
        );
      }

      function getFacebookDate(date){
        var postDate = new Date(date),
            postMonth = postDate.getMonth() + 1,
            postDay = postDate.getDate(),
            postYear = postDate.getFullYear(),
            thisYear = new Date().getFullYear();

        return ((postYear != thisYear ) ? postMonth +"/"+postDay+"/"+postYear: postMonth +"/"+postDay);
      }

      function generatePostMarkup(posts){
        _.each(posts, function(post){
          //Clone our Template
          var $post = cloneTemplate($postTemplate);
          //console.log("The post should be:", $post);
          //Add Title
          if(post.name){
            $post.$title.text(post.name);
          } else {
            $post.$title.remove();
          }

          //Add Link href
          if(post.link){
            $post.$link.attr('href', post.link);
          }

          //Add Date
          if(post.date){
            var postDate = getFacebookDate(post.date);
            $post.$date.text(postDate || '');
          } else {
            $post.$date.remove();
          }

          //Add Photo based on type
          if (post.type === "photo"){
            getImageUrl(post.object_id, function(result){
              $post.$photo.find('img').attr('src', result);
            });
          } else if(post.photo){
            $post.$photo.find('img').attr('src', post.photo);
          }

          //Add Body
          if(post.body){
            $post.$body.html(post.body);
          } else {
            $post.$body.remove();
          }

          //Add Type --> Arguably, this could add a class as well.
          $post.attr('data-post-type', post.type || '');

          //If there's still a loader, kill it.
          $loader.remove();

          //Add That to the List

          $posts.append($post);
        });
        removeTemplate();
        apos.widgetPlayers.facebook.afterLoad($el, posts);
      };

      init();
    }
  );
}

apos.widgetPlayers.facebook.afterLoad = function($el, posts){
  //You can do whatever you want here.
}
<commit_msg>Fixed an issue with dates in Safari and IE<commit_after>apos.widgetPlayers.facebook = function($el) {
  // N.B. Even though this is a player, it's not getting refreshed
  // once it's been created. Hrmmm.

  var data = apos.getWidgetData($el),
      pageUrl = data.pageUrl;

  $.getJSON(
    '/apos-facebook/feed',
    {
      limit: (data.limit || 5),
      pageUrl: pageUrl,
    },
    function(posts) {

      //Define our posts object as well as the template and loader.
      var $posts = $el.find('[data-apos-facebook-posts]'),
          $postTemplate = $posts.find('[data-apos-facebook-post].apos-template'),
          $loader = $posts.find('[data-apos-facebook-loader]');

      if (!posts.length) {
        $el.trigger('aposFacebookNull');
        return;
      }

      function init(){
        removePlaceholder();
        generatePostMarkup(posts);
      }

      function removePlaceholder(){
        $posts.find('[data-apos-facebook-placeholder]').remove();
      }

      function removeTemplate(){
        $postTemplate.remove();
      };

      function buildTemplate($template){
        $template.$title = $template.find('[data-apos-facebook-title]');
        $template.$link = $template.find('[data-apos-facebook-link]');
        $template.$date = $template.find('[data-apos-facebook-date]');
        $template.$photo = $template.find('[data-apos-facebook-photo]');
        $template.$body = $template.find('[data-apos-facebook-body]');
        return $template;
      }

      function cloneTemplate($obj){
        $clone = $obj.clone();
        $clone.removeClass('apos-template');
        clone = buildTemplate($clone);
        return clone;
      }

      function getImageUrl(postId, callback){
        var id = postId;
        $.getJSON(
          '/apos-facebook/photo',
          { id: id},
          function(response) {
            return callback(response);
          }
        );
      }

      function getFacebookDate(date){
        console.log("It was: ", date);

        var postDate = moment(date, 'MM-DD-YYYY'),
            postMonth = postDate.month(),
            postDay = postDate.date(),
            postYear = postDate.year(),
            thisYear = moment().year();
        console.log("For a second it was: ", postDate);
        return ((postYear != thisYear ) ? postMonth +"/"+postDay+"/"+postYear: postMonth +"/"+postDay);
      }

      function generatePostMarkup(posts){
        _.each(posts, function(post){
          //Clone our Template
          var $post = cloneTemplate($postTemplate);
          //console.log("The post should be:", $post);
          //Add Title
          if(post.name){
            $post.$title.text(post.name);
          } else {
            $post.$title.remove();
          }

          //Add Link href
          if(post.link){
            $post.$link.attr('href', post.link);
          }

          //Add Date
          if(post.date){
            var postDate = getFacebookDate(post.date);
            console.log("Now it's: ", postDate);
            $post.$date.text(postDate || '');
          } else {
            $post.$date.remove();
          }

          //Add Photo based on type
          if (post.type === "photo"){
            getImageUrl(post.object_id, function(result){
              $post.$photo.find('img').attr('src', result);
            });
          } else if(post.photo){
            $post.$photo.find('img').attr('src', post.photo);
          }

          //Add Body
          if(post.body){
            $post.$body.html(post.body);
          } else {
            $post.$body.remove();
          }

          //Add Type --> Arguably, this could add a class as well.
          $post.attr('data-post-type', post.type || '');

          //If there's still a loader, kill it.
          $loader.remove();

          //Add That to the List

          $posts.append($post);
        });
        removeTemplate();
        apos.widgetPlayers.facebook.afterLoad($el, posts);
      };

      init();
    }
  );

  Date.fromISO = (function(){
    var testIso = '2011-11-24T09:00:27+0200';
    // Chrome
    var diso= Date.parse(testIso);
    if(diso===1322118027000) return function(s){
        return new Date(Date.parse(s));
    }
    // JS 1.8 gecko
    var noOffset = function(s) {
      var day= s.slice(0,-5).split(/\D/).map(function(itm){
        return parseInt(itm, 10) || 0;
      });
      day[1]-= 1;
      day= new Date(Date.UTC.apply(Date, day));
      var offsetString = s.slice(-5)
      var offset = parseInt(offsetString,10)/100;
      if (offsetString.slice(0,1)=="+") offset*=-1;
      day.setHours(day.getHours()+offset);
      return day.getTime();
    }
    if (noOffset(testIso)===1322118027000) {
       return noOffset;
    }
    return function(s){ // kennebec@SO + QTax@SO
        var day, tz,
        rx = /^(\d{4}\-\d\d\-\d\d([tT][\d:\.]*)?)([zZ]|([+\-])(\d\d):?(\d\d))?$/,

        p= rx.exec(s) || [];
        if(p[1]){
            day= p[1].split(/\D/).map(function(itm){
                return parseInt(itm, 10) || 0;
            });
            day[1]-= 1;
            day= new Date(Date.UTC.apply(Date, day));
            if(!day.getDate()) return NaN;
            if(p[5]){
                tz= parseInt(p[5], 10)/100*60;
                if(p[6]) tz += parseInt(p[6], 10);
                if(p[4]== "+") tz*= -1;
                if(tz) day.setUTCMinutes(day.getUTCMinutes()+ tz);
            }
            return day;
        }
        return NaN;
    }
})()
}

apos.widgetPlayers.facebook.afterLoad = function($el, posts){
  //You can do whatever you want here.
}
<|endoftext|>


<commit_before>document.addEventListener("DOMContentLoaded", function(event) {
    var current_message = {
        thread_id: -1,
        message: '',
        recipient: {},
    };
    var user = local_user_data;
    if ($('#thread-list li').length > 0) {
        onThreadClicked.bind($('#thread-list li').first())();
    }
    $("#conversation-list").scrollTop($("#conversation-list")[0].scrollHeight);

    function newChatBubble (message) {
        var klass = message.author.isMe ? 'myself' : 'other-person';
        var chat = '
'.replace('{who}', klass) +
                        '
{comment}
'.replace('{comment}', message.message) +
                        '
{author}
'.replace('{author}', message.author.name) +
                    '
';
        return chat;
    }

    function serializeDate (date) {
        return date.getHours() + ':' + ('0'+ date.getMinutes()).slice(-2)
    }

    function newThreadItem (data) {
        var image_uri = data.member.profile.picture || '/images/person_placeholder.gif';
        return '
' +
                              '
 ' +
                                  '' +
                                  '
' +
                                    '
' + serializeDate(new Date(data.timeSent)) + '
' +
                                    '
' + data.member.profile.name + '
' +
                                    '
' + data.message + '
' +
                                  '
' +
                              '
' +
                          '
';
    }

    var socket = io();
    $('.message-form').submit(function () {
        var message_text = $('#text-input').val();
        if (!message_text) {
            return false;
        }
        var packet = {
            message: message_text,
            thread_id: current_message.thread_id,
            isNewThread: current_message.thread_id < 0,
            to: [current_message.recipient.id],
        };

        socket.emit('send message', packet);
        $('#text-input').val('');

        return false;
    });

    socket.on('new message', function (data) {
        console.log(JSON.stringify(data, null, 2))
        var match = $('#thread-list').find('[data-thread-id="' + data.thread._id + '"]');
        // If its a message for an existing thread, add it and set that thread to 'pending'
        if (match.length > 0) {
            var message_thread = match[0];
            $(message_thread).find('.message-content').html(data.message);
            var timestamp = new Date(data.timeSent);
            $(message_thread).find('.timestamp').html(serializeDate(timestamp));

            // If its a message for the current thread, make a new chat bubble and append it
            // otherwise just set that thread to be 'pending'
            if (data.thread._id == current_message.thread_id) {
                var new_element = newChatBubble(data);
                $('#conversation-list').append(new_element);
                $("#conversation-list").scrollTop($("#conversation-list")[0].scrollHeight);
                $.ajax({
                    url: '/_ackThread/' + data.thread._id,
                }).done();
                // return here because we don't want to update the unreadThreads
                // count if we are on the current thread.
                return;
            } else {
                $(message_thread).addClass('is-pending');
            }
        } else {
            var member = data.thread._participants.filter(function (person) {
                return person._id != user.id;
            })[0];
            var participant_ids = data.thread._participants.map(function (person) {
                return person._id;
            }).sort();
            var new_thread = newThreadItem({
                member: member,
                timeSent: data.timeSent,
                message: data.message,
                thread_id: data.thread._id,
                participant_ids: JSON.stringify(participant_ids),
            });
            $('#thread-list').prepend(new_thread);
            $('#thread-list li').first().click(onThreadClicked);
            if (current_message.thread_id < 0) {
                onThreadClicked.bind($('#thread-list li').first())();
            } else {
                $('#thread-list li').first().addClass('is-pending');
            }
        }
        $.ajax({
            url: '/_numUnreadThreads',
        }).done(function (data) {
            $('#thread-count').html(data.count);
        });
    });

    function setNodeText (node, new_text) {
        var text_node = node.contents()
            .filter( function () { return this.nodeType == 3; })
            .replaceWith(new_text);
    }

    function onThreadClicked (event) {
        $('#thread-list li').removeClass('is-active');
        $(this).removeClass('is-pending');
        $(this).addClass('is-active');
        var clicked_thread_id = $(this).attr('data-thread-id');
        current_message.thread_id = clicked_thread_id;
        var name = $(this).find('.sender').html();

        $('#conversation-header input').hide();
        $('#conversation-header h3').show();
        setNodeText($("#conversation-header h3"), name);

        $.ajax({
            url: '/_threadMessages/' + clicked_thread_id,
        }).done(function (data) {
            $('#conversation-list').empty();
            var conversation = data.map(function (message) {
                var chat = newChatBubble(message);
                $('#conversation-list').append(chat);
            });
            $.ajax({
                url: '/_ackThread/' + clicked_thread_id,
            }).done(function (data) {
                $('#thread-count').html(data.count);
            });
        });

    }
    $('#thread-list li').click(onThreadClicked);

    $('#new-message-button').click(function () {
        $('#conversation-list').empty();

        var conversation_header = $('#conversation-header h3');
        conversation_header.hide();
         $('#thread-list li').removeClass('is-active');
        var input = $('#conversation-header input');
        input.val('');
        input.show();
        input.focus();

        $('#send-button').attr("disabled", true);
    });

    function autocompleteSelected (event, ui) {
        $('#conversation-header input').hide();
        $('#conversation-header h3').show();
        var participant_id = ui.item.value.id;
        var participant_pic = ui.item.value.pic;
        var participant_name = ui.item.label;
        var thread_matcher = JSON.stringify([participant_id, user.id].sort())
        var match = $('#thread-list').find("[data-thread-participants='" + thread_matcher + "']");
        // If we find a thread matching these participants, then just jump to that thread
        if (match.length > 0) {
            onThreadClicked.bind(match[0])();
        } else {
            // Otherwise, initialize the new thread
            setNodeText($('#conversation-header h3'), participant_name);
            current_message.thread_id = -1;
            current_message.recipient = {
                id: participant_id,
                name: participant_name,
                pic: participant_pic,
            };
        }
        $('#send-button').attr("disabled", false);
    }

    $("#name-input").autocomplete({
        source: '/users/list',
        select: autocompleteSelected,
        focus: function (event, ui) {event.preventDefault();}
    });

    $("#message-search").on('input', function () {
        var query = $("#message-search").val();
        $('#thread-list li').show();
        $('#thread-list li:not(:has(.sender:contains("' + query + '")))').hide();
    });

});
<commit_msg>Force conversation container to scroll to bottom after thread click<commit_after>document.addEventListener("DOMContentLoaded", function(event) {
    var current_message = {
        thread_id: -1,
        message: '',
        recipient: {},
    };
    var user = local_user_data;
    if ($('#thread-list li').length > 0) {
        onThreadClicked.bind($('#thread-list li').first())();
    }

    function newChatBubble (message) {
        var klass = message.author.isMe ? 'myself' : 'other-person';
        var chat = '
'.replace('{who}', klass) +
                        '
{comment}
'.replace('{comment}', message.message) +
                        '
{author}
'.replace('{author}', message.author.name) +
                    '
';
        return chat;
    }

    function serializeDate (date) {
        return date.getHours() + ':' + ('0'+ date.getMinutes()).slice(-2)
    }

    function newThreadItem (data) {
        var image_uri = data.member.profile.picture || '/images/person_placeholder.gif';
        return '
' +
                              '
 ' +
                                  '' +
                                  '
' +
                                    '
' + serializeDate(new Date(data.timeSent)) + '
' +
                                    '
' + data.member.profile.name + '
' +
                                    '
' + data.message + '
' +
                                  '
' +
                              '
' +
                          '
';
    }

    var socket = io();
    $('.message-form').submit(function () {
        var message_text = $('#text-input').val();
        if (!message_text) {
            return false;
        }
        var packet = {
            message: message_text,
            thread_id: current_message.thread_id,
            isNewThread: current_message.thread_id < 0,
            to: [current_message.recipient.id],
        };

        socket.emit('send message', packet);
        $('#text-input').val('');

        return false;
    });

    socket.on('new message', function (data) {
        console.log(JSON.stringify(data, null, 2))
        var match = $('#thread-list').find('[data-thread-id="' + data.thread._id + '"]');
        // If its a message for an existing thread, add it and set that thread to 'pending'
        if (match.length > 0) {
            var message_thread = match[0];
            $(message_thread).find('.message-content').html(data.message);
            var timestamp = new Date(data.timeSent);
            $(message_thread).find('.timestamp').html(serializeDate(timestamp));

            // If its a message for the current thread, make a new chat bubble and append it
            // otherwise just set that thread to be 'pending'
            if (data.thread._id == current_message.thread_id) {
                var new_element = newChatBubble(data);
                $('#conversation-list').append(new_element);
                $("#conversation-list").scrollTop($("#conversation-list")[0].scrollHeight);
                $.ajax({
                    url: '/_ackThread/' + data.thread._id,
                }).done();
                // return here because we don't want to update the unreadThreads
                // count if we are on the current thread.
                return;
            } else {
                $(message_thread).addClass('is-pending');
            }
        } else {
            var member = data.thread._participants.filter(function (person) {
                return person._id != user.id;
            })[0];
            var participant_ids = data.thread._participants.map(function (person) {
                return person._id;
            }).sort();
            var new_thread = newThreadItem({
                member: member,
                timeSent: data.timeSent,
                message: data.message,
                thread_id: data.thread._id,
                participant_ids: JSON.stringify(participant_ids),
            });
            $('#thread-list').prepend(new_thread);
            $('#thread-list li').first().click(onThreadClicked);
            if (current_message.thread_id < 0) {
                onThreadClicked.bind($('#thread-list li').first())();
            } else {
                $('#thread-list li').first().addClass('is-pending');
            }
        }
        $.ajax({
            url: '/_numUnreadThreads',
        }).done(function (data) {
            $('#thread-count').html(data.count);
        });
    });

    function setNodeText (node, new_text) {
        var text_node = node.contents()
            .filter( function () { return this.nodeType == 3; })
            .replaceWith(new_text);
    }

    function onThreadClicked (event) {
        $('#thread-list li').removeClass('is-active');
        $(this).removeClass('is-pending');
        $(this).addClass('is-active');
        var clicked_thread_id = $(this).attr('data-thread-id');
        current_message.thread_id = clicked_thread_id;
        var name = $(this).find('.sender').html();

        $('#conversation-header input').hide();
        $('#conversation-header h3').show();
        setNodeText($("#conversation-header h3"), name);

        $.ajax({
            url: '/_threadMessages/' + clicked_thread_id,
        }).done(function (data) {
            $('#conversation-list').empty();
            var conversation = data.map(function (message) {
                var chat = newChatBubble(message);
                $('#conversation-list').append(chat);
            });
            $("#conversation-list").scrollTop($("#conversation-list")[0].scrollHeight);
            $.ajax({
                url: '/_ackThread/' + clicked_thread_id,
            }).done(function (data) {
                $('#thread-count').html(data.count);
            });
        });

    }
    $('#thread-list li').click(onThreadClicked);

    $('#new-message-button').click(function () {
        $('#conversation-list').empty();

        var conversation_header = $('#conversation-header h3');
        conversation_header.hide();
         $('#thread-list li').removeClass('is-active');
        var input = $('#conversation-header input');
        input.val('');
        input.show();
        input.focus();

        $('#send-button').attr("disabled", true);
    });

    function autocompleteSelected (event, ui) {
        $('#conversation-header input').hide();
        $('#conversation-header h3').show();
        var participant_id = ui.item.value.id;
        var participant_pic = ui.item.value.pic;
        var participant_name = ui.item.label;
        var thread_matcher = JSON.stringify([participant_id, user.id].sort())
        var match = $('#thread-list').find("[data-thread-participants='" + thread_matcher + "']");
        // If we find a thread matching these participants, then just jump to that thread
        if (match.length > 0) {
            onThreadClicked.bind(match[0])();
        } else {
            // Otherwise, initialize the new thread
            setNodeText($('#conversation-header h3'), participant_name);
            current_message.thread_id = -1;
            current_message.recipient = {
                id: participant_id,
                name: participant_name,
                pic: participant_pic,
            };
        }
        $('#send-button').attr("disabled", false);
    }

    $("#name-input").autocomplete({
        source: '/users/list',
        select: autocompleteSelected,
        focus: function (event, ui) {event.preventDefault();}
    });

    $("#message-search").on('input', function () {
        var query = $("#message-search").val();
        $('#thread-list li').show();
        $('#thread-list li:not(:has(.sender:contains("' + query + '")))').hide();
    });

});
<|endoftext|>


<commit_before>var
  picker,
  editor,
  pikatime,
  images,
  datetime_format = 'YYYY-MM-DD hh:mm';

(function() {
  moment.locale("de");
  picker = new Pikaday({
    format: 'DD. MMMM YYYY',
    field: document.getElementById("pikaday"),
    onSelect: pikaday_select
  });

  pikatime = document.getElementById("pikatime");
  pikatime.onchange = pikaday_select;
  set_moment();
  var box = document.querySelector('input[onclick="toggle_event(this)"]')
  toggle_event(box);
  editor = new MediumEditor('#input-editor', {
    placeholder: 'Inhalt',
    buttons: ['bold', 'italic', 'underline', 'anchor', 'header2']
  });

  images = document.getElementById('images')
})();

function toggle_event(checkbox) {
  var input = document.getElementById("date-div");
  if(checkbox.checked) {
    input.className = "show"
  }else {
    input.className = ""
  }
}

function serialize_text() {
  var content = document.getElementById("input-content");
  content.value = editor.serialize()["input-editor"].value;
}

function pikaday_select() {
  var input = document.getElementById("pikaday-field");
  var time = pikatime.value;
  var hour = parseInt(time.substr(0, 2));
  var minute = parseInt(time.substr(2));
  var datetime = picker.getMoment()
  datetime.hour(hour);
  datetime.minute(minute);
  input.value = datetime.format(datetime_format);
}

function set_moment(datetime) {
  if(datetime !== undefined) {
    picker.setMoment(datetime);
    var minute = (Math.round(datetime.minute()/15) * 15) % 60;
    minute = ("00" + String(minute)).slice(-2);
    var hour = datetime.hour();
    hour = ("00" + String(hour)).slice(-2);
    pikatime.value = hour + minute;
  } else {
    var input = document.getElementById("pikaday-field");
    if(input.value !== "") {
      set_moment(moment(input.value, datetime_format))
    }else {
      set_moment(moment());
    }
  }
}

function enumerate_images() {
  var inputs = images.getElementsByTagName('input');
  for (var i = inputs.length - 1; i >= 0; i--) {
    inputs[i].name = 'image' + i;
  };
}

function add_image() {
  var label = document.createElement('label');

  var input = document.createElement('input');
  input.type = 'file';
  input.accept = 'image/*';

  var button = document.createElement('button');
  button.setAttribute('onclick', 'remove_image(this.parentElement); return false;');
  button.className = 'button secondary';
  button.textContent = 'Entfernen';

  label.appendChild(input);
  label.appendChild(button);

  images.appendChild(label);
  enumerate_images()
}

function remove_image(image) {
  image.parentElement.removeChild(image);
  enumerate_images();
}<commit_msg>fixed 24h clock in newpost.js<commit_after>var
  picker,
  editor,
  pikatime,
  images,
  datetime_format = 'YYYY-MM-DD HH:mm';

(function() {
  moment.locale("de");
  picker = new Pikaday({
    format: 'DD. MMMM YYYY',
    field: document.getElementById("pikaday"),
    onSelect: pikaday_select
  });

  pikatime = document.getElementById("pikatime");
  pikatime.onchange = pikaday_select;
  set_moment();
  var box = document.querySelector('input[onclick="toggle_event(this)"]')
  toggle_event(box);
  editor = new MediumEditor('#input-editor', {
    placeholder: 'Inhalt',
    buttons: ['bold', 'italic', 'underline', 'anchor', 'header2']
  });

  images = document.getElementById('images')
})();

function toggle_event(checkbox) {
  var input = document.getElementById("date-div");
  if(checkbox.checked) {
    input.className = "show"
  }else {
    input.className = ""
  }
}

function serialize_text() {
  var content = document.getElementById("input-content");
  content.value = editor.serialize()["input-editor"].value;
}

function pikaday_select() {
  var input = document.getElementById("pikaday-field");
  var time = pikatime.value;
  var hour = parseInt(time.substr(0, 2));
  var minute = parseInt(time.substr(2));
  var datetime = picker.getMoment()
  datetime.hour(hour);
  datetime.minute(minute);
  input.value = datetime.format(datetime_format);
}

function set_moment(datetime) {
  if(datetime !== undefined) {
    picker.setMoment(datetime);
    var minute = (Math.round(datetime.minute()/15) * 15) % 60;
    minute = ("00" + String(minute)).slice(-2);
    var hour = datetime.hour();
    hour = ("00" + String(hour)).slice(-2);
    pikatime.value = hour + minute;
  } else {
    var input = document.getElementById("pikaday-field");
    if(input.value !== "") {
      set_moment(moment(input.value, datetime_format))
    }else {
      set_moment(moment());
    }
  }
}

function enumerate_images() {
  var inputs = images.getElementsByTagName('input');
  for (var i = inputs.length - 1; i >= 0; i--) {
    inputs[i].name = 'image' + i;
  };
}

function add_image() {
  var label = document.createElement('label');

  var input = document.createElement('input');
  input.type = 'file';
  input.accept = 'image/*';

  var button = document.createElement('button');
  button.setAttribute('onclick', 'remove_image(this.parentElement); return false;');
  button.className = 'button secondary';
  button.textContent = 'Entfernen';

  label.appendChild(input);
  label.appendChild(button);

  images.appendChild(label);
  enumerate_images()
}

function remove_image(image) {
  image.parentElement.removeChild(image);
  enumerate_images();
}<|endoftext|>


<commit_before>/* globals google, expenseRestShow:true, incomeRestShow:true, year, shared, month, hideTheRest, showTheRest, showTheRestExpense, hideTheRestExpense, columnChart, lineChart, stackedColumnChart */

$(function () {
    "use strict";
    drawChart();

    $('#inputDateRange').daterangepicker(
        {
            minDate: minDate,
            drops: 'up',
        }
    );

    $('.openModal').on('click', openModal);

    // click open the top X income list:
    $('#showIncomes').click(showIncomes);
    // click open the top X expense list:
    $('#showExpenses').click(showExpenses);
});

function drawChart() {
    "use strict";
    if (typeof columnChart !== 'undefined' && typeof year !== 'undefined' && typeof month === 'undefined') {
        columnChart('chart/report/in-out/' + year + shared, 'income-expenses-chart');
        columnChart('chart/report/in-out-sum/' + year + shared, 'income-expenses-sum-chart');
    }
    if (typeof stackedColumnChart !== 'undefined' && typeof year !== 'undefined' && typeof month === 'undefined') {
        stackedColumnChart('chart/budget/year/' + year + shared, 'budgets');
        stackedColumnChart('chart/category/spent-in-year/' + year + shared, 'categories-spent-in-year');
        stackedColumnChart('chart/category/earned-in-year/' + year + shared, 'categories-earned-in-year');
    }
    if (typeof lineChart !== 'undefined' && typeof month !== 'undefined') {
        lineChart('/chart/account/month/' + year + '/' + month + shared, 'account-balances-chart');
    }
}

function openModal(e) {
    "use strict";
    var target = $(e.target).parent();
    var URL = target.attr('href');

    $.get(URL).success(function (data) {
        $('#defaultModal').empty().html(data).modal('show');

    }).fail(function () {
        alert('Could not load data.');
    });

    return false;
}

function showIncomes() {
    "use strict";
    if (incomeRestShow) {
        // hide everything, make button say "show"
        $('#showIncomes').text(showTheRest);
        $('.incomesCollapsed').removeClass('in').addClass('out');

        // toggle:
        incomeRestShow = false;
    } else {
        // show everything, make button say "hide".
        $('#showIncomes').text(hideTheRest);
        $('.incomesCollapsed').removeClass('out').addClass('in');

        // toggle:
        incomeRestShow = true;
    }

    return false;
}

function showExpenses() {
    "use strict";
    if (expenseRestShow) {
        // hide everything, make button say "show"
        $('#showExpenses').text(showTheRestExpense);
        $('.expenseCollapsed').removeClass('in').addClass('out');

        // toggle:
        expenseRestShow = false;
    } else {
        // show everything, make button say "hide".
        $('#showExpenses').text(hideTheRestExpense);
        $('.expenseCollapsed').removeClass('out').addClass('in');

        // toggle:
        expenseRestShow = true;
    }

    return false;
}<commit_msg>Some mediocre Javascript for report thing.<commit_after>/* globals google, picker:true, minDate, expenseRestShow:true, incomeRestShow:true, year, shared, month, hideTheRest, showTheRest, showTheRestExpense, hideTheRestExpense, columnChart, lineChart, stackedColumnChart */

$(function () {
    "use strict";
    drawChart();

    picker = $('#inputDateRange').daterangepicker(
        {
            locale: {
                format: 'YYYY-MM-DD',
                firstDay: 1,
            },
            minDate: minDate,
            drops: 'up',
        }
    );

    $('.openModal').on('click', openModal);

    $('.date-select').on('click',preSelectDate);

    // click open the top X income list:
    $('#showIncomes').click(showIncomes);
    // click open the top X expense list:
    $('#showExpenses').click(showExpenses);
});

function preSelectDate(e) {
    "use strict";
    var link = $(e.target);
    var picker = $('#inputDateRange').data('daterangepicker');
    picker.setStartDate(link.data('start'));
    picker.setEndDate(link.data('end'));
    return false;

}

function drawChart() {
    "use strict";
    if (typeof columnChart !== 'undefined' && typeof year !== 'undefined' && typeof month === 'undefined') {
        columnChart('chart/report/in-out/' + year + shared, 'income-expenses-chart');
        columnChart('chart/report/in-out-sum/' + year + shared, 'income-expenses-sum-chart');
    }
    if (typeof stackedColumnChart !== 'undefined' && typeof year !== 'undefined' && typeof month === 'undefined') {
        stackedColumnChart('chart/budget/year/' + year + shared, 'budgets');
        stackedColumnChart('chart/category/spent-in-year/' + year + shared, 'categories-spent-in-year');
        stackedColumnChart('chart/category/earned-in-year/' + year + shared, 'categories-earned-in-year');
    }
    if (typeof lineChart !== 'undefined' && typeof month !== 'undefined') {
        lineChart('/chart/account/month/' + year + '/' + month + shared, 'account-balances-chart');
    }
}

function openModal(e) {
    "use strict";
    var target = $(e.target).parent();
    var URL = target.attr('href');

    $.get(URL).success(function (data) {
        $('#defaultModal').empty().html(data).modal('show');

    }).fail(function () {
        alert('Could not load data.');
    });

    return false;
}

function showIncomes() {
    "use strict";
    if (incomeRestShow) {
        // hide everything, make button say "show"
        $('#showIncomes').text(showTheRest);
        $('.incomesCollapsed').removeClass('in').addClass('out');

        // toggle:
        incomeRestShow = false;
    } else {
        // show everything, make button say "hide".
        $('#showIncomes').text(hideTheRest);
        $('.incomesCollapsed').removeClass('out').addClass('in');

        // toggle:
        incomeRestShow = true;
    }

    return false;
}

function showExpenses() {
    "use strict";
    if (expenseRestShow) {
        // hide everything, make button say "show"
        $('#showExpenses').text(showTheRestExpense);
        $('.expenseCollapsed').removeClass('in').addClass('out');

        // toggle:
        expenseRestShow = false;
    } else {
        // show everything, make button say "hide".
        $('#showExpenses').text(hideTheRestExpense);
        $('.expenseCollapsed').removeClass('out').addClass('in');

        // toggle:
        expenseRestShow = true;
    }

    return false;
}<|endoftext|>


<commit_before>// master array for fraenks
var fraenks = [];

// disable double tap zoom via plugin
$('#stage,.fraenk,#slaps-container,#menu').nodoubletapzoom();

// setting up menu
$(document).ready(function() {

  // name prompt menu item
  $('#menu-your-name').on("click", function() {
/*    bootbox.prompt("
What is your name?
Your name is only used for the fränk high score table.", function(result) {
      if (result === null) {
//          no name given
      } else {
//          send name to server
      }
    })*/
    bootbox.alert("note yet...");
  });

  // about menu item
  $('#menu-about').on("click", function() {
    bootbox.alert("
About fränk
fränk is an experimental multiplayer game that can be deployed locally, for example using Raspberry Pi as a gaming hub, but also in the internet. This game was created by Jani Turunen, 2013.");
  });

  // connection test menu item
  $('#menu-connection-test').on("click", function() {
    bootbox.alert("
Hit OK to ping server ...
", function() {
      socket.emit('ping',Date.now().toString());
    });
  });

  // instructions menu item
  $('#menu-instructions').on("click", function() {
    bootbox.alert("
How to play fränk
At this point, just keep clicking! We'll add scores and gameplay later!");
  });

});

// setting up socket
var socket = io.connect(window.location.hostname);

// when socket receives ping respond with pong
socket.on('pong', function (data) {
  var lag = Date.now() - parseInt(data);
  bootbox.alert("
Ping time: "+lag+"ms
");
})

// when socket receives ping respond with pong
socket.on('fraenks', function (data) {
  // delete all existing fraenks
  $('.fraenk').remove();
  fraenks = []

  // spawn new ones
  jQuery.each(data, function(frank) {
    var f = new fraenk();
    f.create(data[frank].id);
    f.animate(19,11);
    f.wander();
    fraenks.push(f);
  });
  $('.fraenk').nodoubletapzoom();
})

// kill individual fraenks when some other player has nuked them
socket.on('kill', function(data) {
  $('#'+data[0].id).remove();
});

// loop for adding slaps
var slaps = 0
  , max_slaps = 5;
var slap_loop = setInterval(function() {
  if (slaps < max_slaps) {
    var html = "";
    for (var i=0; i<max_slaps; i++) {
      html += '

';
    }
    slaps = max_slaps
    $('#slaps-container').empty();
    $('#slaps-container').html(html);
  }
},5000);

// removing slaps for misses
$('#stage').on('click', function() {
  remove_slap();
});

function remove_slap() {
  slaps -= 1;
  $('#slaps-container div:last-child').remove();
}

function fraenk() {
  this.id = null;
  this.create = function(id) {
    this.id = id;
    this.ele = $('
').appendTo('body');
    this.ele.on('click', function() {
      if (slaps < 1) return;
      $(this).destroy();
      remove_slap();
//      $(this).transition({ rotate: '360deg' })
      $(this).remove();
      socket.emit('kill',$(this).attr('id'));
    });
  },
  this.animate = function(max, min) {
    var f = Math.floor(Math.random() * (max - min + 1)) + min;
    this.ele.sprite({fps: f, no_of_frames: 4})
  },
  this.wander = function() {
    this.ele.spRandom({top: -100, bottom: $(document).height()+50, left: -100, right: $(document).width()+50})
  }
}<commit_msg>credits<commit_after>// master array for fraenks
var fraenks = [];

// disable double tap zoom via plugin
$('#stage,.fraenk,#slaps-container,#menu').nodoubletapzoom();

// setting up menu
$(document).ready(function() {

  // name prompt menu item
  $('#menu-your-name').on("click", function() {
/*    bootbox.prompt("
What is your name?
Your name is only used for the fränk high score table.", function(result) {
      if (result === null) {
//          no name given
      } else {
//          send name to server
      }
    })*/
    bootbox.alert("note yet...");
  });

  // about menu item
  $('#menu-about').on("click", function() {
    bootbox.alert("
About fränk
fränk is an experimental multiplayer game that can be deployed locally, for example using Raspberry Pi as a gaming hub, but also in the internet. This game was created by Jani Turunen & Kare Nieminen, Helsinki, 2013.");
  });

  // connection test menu item
  $('#menu-connection-test').on("click", function() {
    bootbox.alert("
Hit OK to ping server ...
", function() {
      socket.emit('ping',Date.now().toString());
    });
  });

  // instructions menu item
  $('#menu-instructions').on("click", function() {
    bootbox.alert("
How to play fränk
At this point, just keep clicking! We'll add scores and gameplay later!");
  });

});

// setting up socket
var socket = io.connect(window.location.hostname);

// when socket receives ping respond with pong
socket.on('pong', function (data) {
  var lag = Date.now() - parseInt(data);
  bootbox.alert("
Ping time: "+lag+"ms
");
})

// when socket receives ping respond with pong
socket.on('fraenks', function (data) {
  // delete all existing fraenks
  $('.fraenk').remove();
  fraenks = []

  // spawn new ones
  jQuery.each(data, function(frank) {
    var f = new fraenk();
    f.create(data[frank].id);
    f.animate(19,11);
    f.wander();
    fraenks.push(f);
  });
  $('.fraenk').nodoubletapzoom();
})

// kill individual fraenks when some other player has nuked them
socket.on('kill', function(data) {
  $('#'+data[0].id).remove();
});

// loop for adding slaps
var slaps = 0
  , max_slaps = 5;
var slap_loop = setInterval(function() {
  if (slaps < max_slaps) {
    var html = "";
    for (var i=0; i<max_slaps; i++) {
      html += '

';
    }
    slaps = max_slaps
    $('#slaps-container').empty();
    $('#slaps-container').html(html);
  }
},5000);

// removing slaps for misses
$('#stage').on('click', function() {
  remove_slap();
});

function remove_slap() {
  slaps -= 1;
  $('#slaps-container div:last-child').remove();
}

function fraenk() {
  this.id = null;
  this.create = function(id) {
    this.id = id;
    this.ele = $('
').appendTo('body');
    this.ele.on('click', function() {
      if (slaps < 1) return;
      $(this).destroy();
      remove_slap();
//      $(this).transition({ rotate: '360deg' })
      $(this).remove();
      socket.emit('kill',$(this).attr('id'));
    });
  },
  this.animate = function(max, min) {
    var f = Math.floor(Math.random() * (max - min + 1)) + min;
    this.ele.sprite({fps: f, no_of_frames: 4})
  },
  this.wander = function() {
    this.ele.spRandom({top: -100, bottom: $(document).height()+50, left: -100, right: $(document).width()+50})
  }
}<|endoftext|>


<commit_before>/* globals define, app, ajaxify, bootbox, socket, templates, utils */

$(document).ready(function () {
    'use strict';

    require([
        'forum/topic/images',
        'translator'
    ], function (images, translator) {

        var elements = {
            BUTTON : '.ns-spoiler-control a',
            CONTENT: '.ns-spoiler-content',
            MAIN   : '.ns-spoiler',
            POST   : '[component="post"]'
        }, classes   = {
            OPEN_EYE : 'fa-eye',
            CLOSE_EYE: 'fa-eye-slash'
        };

        $(window).on('action:topic.loading', function (e) {
            addTopicListener();
        });

        function addTopicListener() {
            $('[component="topic"]').on("click", elements.BUTTON, function () {
                toggle($(this));
            });
        }

        function toggle($button) {
            var $spoiler = $button.parents(elements.MAIN),
                $content = $spoiler.find(elements.CONTENT),
                open     = $spoiler.attr('data-open') === 'true',
                postId   = parseInt($spoiler.parents('[data-pid]').attr('data-pid')),
                index    = parseInt($spoiler.attr('data-index')),
                icon     = $button.find('i');

            $spoiler.attr('data-open', !open);

            if (!open) {
                icon.removeClass(classes.OPEN_EYE).addClass(classes.CLOSE_EYE);
            } else {
                icon.removeClass(classes.CLOSE_EYE).addClass(classes.OPEN_EYE);
            }

            // Check if content is empty
            if ($content.html().length === 0) {
                socket.emit(
                    'plugins.ns-spoiler.getSpoilerContent',
                    {index: index, postId: postId},
                    function (error, content) {
                        if (error) {
                            return console.error('Error has occurred, error: %s', error.message);
                        }
                        $content.html(content);
                        images.unloadImages($spoiler.parents(elements.POST));
                        images.loadImages();
                    }
                );
            }

        }
    });
});
<commit_msg>change client code loading<commit_after>/* globals define, app, ajaxify, bootbox, socket, templates, utils */

require([
    'forum/topic/images',
    'translator'
], function (images, translator) {

    var elements = {
        BUTTON : '.ns-spoiler-control a',
        CONTENT: '.ns-spoiler-content',
        MAIN   : '.ns-spoiler',
        POST   : '[component="post"]'
    }, classes   = {
        OPEN_EYE : 'fa-eye',
        CLOSE_EYE: 'fa-eye-slash'
    };

    $(window).on('action:topic.loading', function (e) {
        addTopicListener();
    });

    function addTopicListener() {
        $('[component="topic"]').on("click", elements.BUTTON, function () {
            toggle($(this));
        });
    }

    function toggle($button) {
        var $spoiler = $button.parents(elements.MAIN),
            $content = $spoiler.find(elements.CONTENT),
            open     = $spoiler.attr('data-open') === 'true',
            postId   = parseInt($spoiler.parents('[data-pid]').attr('data-pid')),
            index    = parseInt($spoiler.attr('data-index')),
            icon     = $button.find('i');

        $spoiler.attr('data-open', !open);

        if (!open) {
            icon.removeClass(classes.OPEN_EYE).addClass(classes.CLOSE_EYE);
        } else {
            icon.removeClass(classes.CLOSE_EYE).addClass(classes.OPEN_EYE);
        }

        // Check if content is empty
        if ($content.html().length === 0) {
            socket.emit(
                'plugins.ns-spoiler.getSpoilerContent',
                {index: index, postId: postId},
                function (error, content) {
                    if (error) {
                        return console.error('Error has occurred, error: %s', error.message);
                    }
                    $content.html(content);
                    images.unloadImages($spoiler.parents(elements.POST));
                    images.loadImages();
                }
            );
        }

    }
});
<|endoftext|>


<commit_before>
var SC=µ.shortcut({
	Config:"Config",
	File:"File"
});

var config=SC.Config.parse({
	"create Package":{
		type:"boolean",
		default:true
	},
	"append CRC32":{
		type:"boolean",
		default:true
	},
	"check name":{
		type:"boolean",
		default:true
	},
	"clean name":{
		type:"boolean",
		default:true
	},
	"file expiration":{
		type:"number",
		min:0,
		default:6
	},
	"search timeout":{
		type:"number",
		min:500,
		max:50000,
		default:15000
	},
	"search sources":{
		type:"map",
		model:{
			type:"boolean",
			default:true
		}
	}
});

module.exports=worker.configManager(config);
module.exports.config=config;

new SC.File("subOffices").listFiles().then(function(subOfficeList)
{

	var searchSources=config.get("search sources");
	for(var subOffice of subOfficeList)
	{
		searchSources.add(subOffice);
	}
});<commit_msg>move configManager to util folder and add resouceFolder to µ<commit_after>
var SC=µ.shortcut({
	Config:"Config",
	File:"File"
});

var config=SC.Config.parse({
	"create Package":{
		type:"boolean",
		default:true
	},
	"append CRC32":{
		type:"boolean",
		default:true
	},
	"check name":{
		type:"boolean",
		default:true
	},
	"clean name":{
		type:"boolean",
		default:true
	},
	"file expiration":{
		type:"number",
		min:0,
		default:6
	},
	"search timeout":{
		type:"number",
		min:500,
		max:50000,
		default:15000
	},
	"search sources":{
		type:"map",
		model:{
			type:"boolean",
			default:true
		}
	}
});

module.exports=µ.getModule("configManager")(config);
module.exports.config=config;

new SC.File("subOffices").listFiles().then(function(subOfficeList)
{

	var searchSources=config.get("search sources");
	for(var subOffice of subOfficeList)
	{
		searchSources.add(subOffice);
	}
});<|endoftext|>


<commit_before>'use strict';

var log4js = require('log4js');
var logger = log4js.getLogger();
var express = require('express');
var favicon = require('serve-favicon');
var bodyParser = require('body-parser');
var port = process.env.OPENSHIFT_NODEJS_PORT || 3000;
var ipaddress = process.env.OPENSHIFT_NODEJS_IP;
var loglevel = process.env.LOGLEVEL || 'DEBUG';

var app = express();

// Enforce https redirect if appropriate
app.enable('trust proxy');
app.use(function (req, res, next) {
	// Redirect to https only if the app is deployed
	if (/rikitraki/i.test(req.headers.host)) {
		if (req.secure) {
			next();
		} else {
			res.redirect('https://' + req.headers.host + req.url);
		}
	} else {
		next();
	}
});

// app.use(favicon(__dirname + '/public/favicon.ico'));

logger.setLevel(loglevel);
// app.use(express.static('public'));

app.use(log4js.connectLogger(log4js.getLogger('http'), { level: 'auto' }));
app.use(bodyParser.json({limit: '5mb'}));
app.use(bodyParser.raw({limit: '10mb', type: 'image/jpeg'}));

app.use('/api/', require('./routes/').router);

app.listen(port, ipaddress, function () {
	logger.info('starting rikitrakiws', this.address());
});
<commit_msg>Remove https redirect (move to apache)<commit_after>'use strict';

var log4js = require('log4js');
var logger = log4js.getLogger();
var express = require('express');
var favicon = require('serve-favicon');
var bodyParser = require('body-parser');
var port = process.env.OPENSHIFT_NODEJS_PORT || 3000;
var ipaddress = process.env.OPENSHIFT_NODEJS_IP;
var loglevel = process.env.LOGLEVEL || 'DEBUG';

var app = express();

// Enforce https redirect if appropriate
/*app.enable('trust proxy');
app.use(function (req, res, next) {
	// Redirect to https only if the app is deployed
	if (/rikitraki/i.test(req.headers.host)) {
		if (req.secure) {
			next();
		} else {
			res.redirect('https://' + req.headers.host + req.url);
		}
	} else {
		next();
	}
});*/

// app.use(favicon(__dirname + '/public/favicon.ico'));

logger.setLevel(loglevel);
// app.use(express.static('public'));

app.use(log4js.connectLogger(log4js.getLogger('http'), { level: 'auto' }));
app.use(bodyParser.json({limit: '5mb'}));
app.use(bodyParser.raw({limit: '10mb', type: 'image/jpeg'}));

app.use('/api/', require('./routes/').router);

app.listen(port, ipaddress, function () {
	logger.info('starting rikitrakiws', this.address());
});
<|endoftext|>


<commit_before>'use strict'
module.exports = getFic

const fs = require('fs')
const url = require('url')

const Chapter = use('fic').Chapter
const FicStream = use('fic-stream')
const html = use('html-template-tag')
const progress = use('progress')
const Site = use('site')
const forEach = use('for-each')
const map = use('map')

function rewriteLinks (fic, chapter, handleLink) {
  chapter.$content.find('a').each((ii, a) => {
    const $a = chapter.$content.find(a)
    const startAs = $a.attr('href')
    if (!startAs) {
      $a.remove()
      return
    }
    if (startAs[0] === '#') return
    let src
    if (startAs.substr(0,4) !== 'http' && /^www[.]|[.]com$/.test(startAs)) {
      src = 'http://' + startAs
    } else {
      src = chapter.base ? url.resolve(chapter.base, startAs) : startAs
    }
    const newHref = handleLink(fic.normalizeLink(src, chapter.base), $a)
    $a.attr('href', newHref || src)
  })
}

function rewriteIframes (fic, chapter) {
  chapter.$content.find('iframe').each((ii, iframe) => {
    const $iframe = chapter.$content.find(iframe)
    const src = url.resolve(chapter.base, $iframe.attr('src'))
    $iframe.replaceWith(`<a href="${src}">Video Link</a>`)
  })
}

function rewriteImages (fic, chapter, handleImage) {
  chapter.$content.find('img').each((ii, img) => {
    const $img = chapter.$content.find(img)
    const startAs = ($img.attr('src') || '').replace(/(https?:[/])([^/])/, '$1/$2')
    if (!startAs) return
    const src = url.resolve(chapter.base, startAs)
    if (!url.parse(src).hostname) return
    const newsrc = handleImage(fic.normalizeLink(src, chapter.base), $img)
    $img.attr('src', newsrc || src)
  })
}

function findChapter (href, fic) {
  const matching = fic.chapters.filter(index => fic.normalizeLink(index.link) === fic.normalizeLink(href))
  return matching && matching[0]
}

function externalName (external) {
  return `_LINK_external#LINK#${external.num||external.order}#LINK#_LINK_`
}
function chapterLinkname (chapter) {
  return `_LINK_chapter#LINK#${chapter.num||chapter.order}#LINK#${chapter.name||''}_LINK_`
}

function inlineImages (images) {
  return (src, $img) => {
    if (/clear[.]png$/.test(src)) return // xenforo
    if (/Special:CentralAutoLogin/.test(src)) return // wikipedia
    src = src.replace(/^https?:[/][/]api[.]imgble[.]com[/](.*)[/]\d+[/]\d+$/, '$1')
    src = src.replace(/\b(?:41|36|67)[.]media[.]tumblr[.]com\b/, '40.media.tumblr.com')
    if (!images[src]) {
      let ext = src.match(/([.](?:jpe?g|gif|png))/i) || src.match(/([.]svg)/i)
      ext = ext && ext[1]
      if (ext === '.svg' && /wikia.nocookie.net/.test(src)) ext = '.png'
      if (ext === '.jpeg') ext = '.jpg'
      images[src] = {
        filename: `image-${Object.keys(images).length + 1}${ext || '.guess.jpg'}`
      }
    }
    return images[src].filename
  }
}

function linklocalChapters (fic, externals) {
  return (href, $a, orElse) => {
    if (!orElse) orElse = () => { }
    if ($a.text() === '↑') {
      $a.remove()
      return
    }
    if ($a.attr('external') === 'false') return
    const linkedChapter = findChapter(href, fic)
    if (linkedChapter) {
      return chapterLinkname(linkedChapter)
    } else if (externals[href]) {
      return externalName(externals[href])
    } else {
      return orElse(href) || href
    }
  }
}

function getFic (fetch, fic) {
  const stream = new FicStream(fic, {highWaterMark: 8})
  const externals = {}
  const images = {}
  const chapters = fic.chapters.filter(ch => ch.type !== 'Staff Post')
  const maxConcurrency = 40 // limit saves memory, not network, network is protected elsewhere

  process.emit('debug', `Outputting ${chapters.length} chapters of ${fic.title}`)
  let completed = 0
  let headIndex = 0
  let tailIndex = 0
  function showChapterStatus () {
    progress.show(`Fetching chapters [${completed}/${chapters.length}]`)
  }
  showChapterStatus()
  const finishedChapters = []

  const identifyBuffer = require('buffer-signature').identify
  async function addImage (src, type, filename) {
    if (!src) return
    process.emit('debug', `Outputting ${type} of ${fic.title}`)
    if (/:/.test(src)) {
      fetch.tracker.addWork(1)
      progress.show('Fetching ${type}…')
      try {
        const [meta, imageData] = await fetch(src, {referer: fic.link})
        const info = identifyBuffer(imageData)
        if (filename && !/[.]\w+$/.test(filename) && info.extensions.length) {
          filename += '.' + info.extensions[0]
        }

        const chapter = {
          outputType: type,
          content: imageData,
          mime: info.mimeType
        }
        if (filename) chapter.filename = filename
        await stream.queueChapter(chapter)
      } catch (err) {
        process.emit('error', `Error while fetching ${type} ${src}: ${err.message}`)
      }
    } else {
      await stream.queueChapter({
        outputType: type,
        content: fs.createReadStream(src)
      })
    }
  }

  process.emit('debug', `Considering art`)

  // we return `stream` and this feeds it, so it's intentionally allowed to
  // go off async and not be captured
  Promise.all([addImage(fic.cover, 'cover', 'cover'), addImage(fic.art, 'art', 'art')])
  .then(() => forEach(chapters, async chapterInfo => {
    try {
      const chapter = await chapterInfo.getContent(fetch)

      chapterInfo.order = chapter.order = chapterInfo.type === 'chapter' ? headIndex++ : (8000 + tailIndex ++)
      if (chapterInfo.type !== 'chapter' && !/:/.test(chapter.name)) {
        chapter.name = `${chapterInfo.type}: ${chapterInfo.name}`
      }
      if ((fic.chapterHeadings && chapterInfo.headings !== false) || chapterInfo.headings) {
        const headerName = html`${chapterInfo.name}`
        const byline = !chapterInfo.author ? ''
          : (' by ' + (!chapterInfo.authorUrl ? chapterInfo.author
            : html`<a href="${chapterInfo.authorUrl}">${chapterInfo.author}</a>`))
        const headerLine = `<header><h2>${headerName}${byline}</h2></header>`
        chapter.content = headerLine + chapter.content
      }
      rewriteImages(fic, chapter, inlineImages(images))
      rewriteIframes(fic, chapter)
      chapter.outputType = 'chapter'
      finishedChapters.push({info: chapterInfo, content: chapter})
    } catch (err) {
      process.emit('error', 'Error while fetching chapter', chapterInfo, err.stack)
    } finally {
      ++completed
      showChapterStatus()
    }
  })).then(async () => {
    completed = 0
    showChapterStatus()
    await forEach(finishedChapters, async (chapter, ii) => {
      rewriteLinks(fic, chapter.content, (href, $a) => {
        return linklocalChapters(fic, externals)(href, $a, (href) => {
          if (!chapter.info.externals || !fic.externals) return
          try {
            Site.fromUrl(href)
          } catch (ex) {
            return
          }
          externals[href] = {
            order: 9000 + Object.keys(externals).length,
            num: Object.keys(externals).length + 1,
            requestedBy: chapter.info
          }
          return externalName(externals[href])
        })
      })

      await stream.queueChapter(chapter.content)
      ++completed
      showChapterStatus()
    })

    const externalCount = Object.keys(externals).length
    process.emit('debug', `Outputting ${externalCount} externals of ${fic.title}`)
    fetch.tracker.addWork(externalCount)
    completed = 0
    function showExternalStatus () {
      progress.show(`Fetching externals [${completed}/${externalCount}]`)
    }
    showExternalStatus()
    const pages = externalCount === 1 ? 'page' : 'pages'
    await forEach(Object.keys(externals), maxConcurrency, async (href, exterNum) => {
      const externalInfo = externals[href]
      try {
        const external = await Chapter.getContent(fetch, href)
        external.order = externalInfo.order
        external.num = externalInfo.num
        const name = external.name || external.ficTitle
        let header = ''
        const linkSource = externalInfo.requestedBy.link || externalInfo.requestedBy.fetchFrom
        header += `<div>Linked to from: <a href="${linkSource}">${externalInfo.requestedBy.name}</a></div>`
        const byline = !external.author ? ''
          : (!external.authorUrl ? external.author : html`<a href="${external.authorUrl}">${external.author}</a>`)
        if (name) {
          const headerName = html`${name}`
          header += `<header><h2><a external="false" href="${href}">${headerName}</a>${byline ? ' by ' + byline : ''}</h2></header>`
        } else if (byline) {
          const wrappableLink = href.replace(/(.....)/g, '$1<wbr>')
          header += `<header><h2><div style="font-size: 11px"><a external="false" href="${href}">${wrappableLink}</a></div>`
          header += `by ${byline}</h2></header>`
        }
        external.content = `${header}<hr>${external.content}`
        external.name = exterNum ? null : `External References (${externalCount} ${pages})`
        external.filename = externalName(external)
        external.outputType = 'external'
        rewriteImages(fic, external, inlineImages(images))
        rewriteLinks(fic, external, linklocalChapters(fic, externals))
        rewriteIframes(fic, external)
        await stream.queueChapter(external)
      } catch (err) {
        process.emit('error', `Warning, skipping external ${href}: ${err.stack}`)
        await stream.queueChapter({
          order: 9000 + exterNum,
          name: exterNum ? null : `External References (${externalCount} ${pages})`,
          filename: externalName(externals[href]),
          outputType: 'external',
          content: html`<p>External link to <a href="${href}">${href}</a></p><pre>${err.stack}</pre>`
        })
      } finally {
        ++completed
        showExternalStatus()
      }
    })

    const imageCount = Object.keys(images).length
    fetch.tracker.addWork(imageCount)
    completed = 0
    function showImageStatus () {
      progress.show(`Fetching images [${completed}/${imageCount}]`)
    }
    showImageStatus()
    await forEach(Object.keys(images), maxConcurrency, async (src, imageNum) => {
      try {
        await addImage(src, 'image', images[src].filename)
      } catch (err) {
        process.emit('error', `Error while fetching image ${src}: ${err.message}`)
      } finally {
        ++completed
        showImageStatus()
      }
    })

    process.emit('debug', `Outputting ${fic.title} complete`)
    return stream.queueChapter(null)
  }).catch(err => {
    process.emit('error', `Error in get fic ${err.stack}`)
  })

  return stream
}
<commit_msg>get-fic: Detect more urls w/o protocols<commit_after>'use strict'
module.exports = getFic

const fs = require('fs')
const url = require('url')

const Chapter = use('fic').Chapter
const FicStream = use('fic-stream')
const html = use('html-template-tag')
const progress = use('progress')
const Site = use('site')
const forEach = use('for-each')
const map = use('map')

function rewriteLinks (fic, chapter, handleLink) {
  chapter.$content.find('a').each((ii, a) => {
    const $a = chapter.$content.find(a)
    const startAs = $a.attr('href')
    if (!startAs) {
      $a.remove()
      return
    }
    if (startAs[0] === '#') return
    let src
    if (startAs.substr(0,4) !== 'http' && /^www[.]|[.]com$/.test(startAs)) {
      src = 'http://' + startAs
    } else if (/^[\w.]+(com|org|net)[/]/.test(startAs)) {
      src = 'http://' + startAs
    } else {
      src = chapter.base ? url.resolve(chapter.base, startAs) : startAs
    }
    const newHref = handleLink(fic.normalizeLink(src, chapter.base), $a)
    $a.attr('href', newHref || src)
  })
}

function rewriteIframes (fic, chapter) {
  chapter.$content.find('iframe').each((ii, iframe) => {
    const $iframe = chapter.$content.find(iframe)
    const src = url.resolve(chapter.base, $iframe.attr('src'))
    $iframe.replaceWith(`<a href="${src}">Video Link</a>`)
  })
}

function rewriteImages (fic, chapter, handleImage) {
  chapter.$content.find('img').each((ii, img) => {
    const $img = chapter.$content.find(img)
    const startAs = ($img.attr('src') || '').replace(/(https?:[/])([^/])/, '$1/$2')
    if (!startAs) return
    const src = url.resolve(chapter.base, startAs)
    if (!url.parse(src).hostname) return
    const newsrc = handleImage(fic.normalizeLink(src, chapter.base), $img)
    $img.attr('src', newsrc || src)
  })
}

function findChapter (href, fic) {
  const matching = fic.chapters.filter(index => fic.normalizeLink(index.link) === fic.normalizeLink(href))
  return matching && matching[0]
}

function externalName (external) {
  return `_LINK_external#LINK#${external.num||external.order}#LINK#_LINK_`
}
function chapterLinkname (chapter) {
  return `_LINK_chapter#LINK#${chapter.num||chapter.order}#LINK#${chapter.name||''}_LINK_`
}

function inlineImages (images) {
  return (src, $img) => {
    if (/clear[.]png$/.test(src)) return // xenforo
    if (/Special:CentralAutoLogin/.test(src)) return // wikipedia
    src = src.replace(/^https?:[/][/]api[.]imgble[.]com[/](.*)[/]\d+[/]\d+$/, '$1')
    src = src.replace(/\b(?:41|36|67)[.]media[.]tumblr[.]com\b/, '40.media.tumblr.com')
    if (!images[src]) {
      let ext = src.match(/([.](?:jpe?g|gif|png))/i) || src.match(/([.]svg)/i)
      ext = ext && ext[1]
      if (ext === '.svg' && /wikia.nocookie.net/.test(src)) ext = '.png'
      if (ext === '.jpeg') ext = '.jpg'
      images[src] = {
        filename: `image-${Object.keys(images).length + 1}${ext || '.guess.jpg'}`
      }
    }
    return images[src].filename
  }
}

function linklocalChapters (fic, externals) {
  return (href, $a, orElse) => {
    if (!orElse) orElse = () => { }
    if ($a.text() === '↑') {
      $a.remove()
      return
    }
    if ($a.attr('external') === 'false') return
    const linkedChapter = findChapter(href, fic)
    if (linkedChapter) {
      return chapterLinkname(linkedChapter)
    } else if (externals[href]) {
      return externalName(externals[href])
    } else {
      return orElse(href) || href
    }
  }
}

function getFic (fetch, fic) {
  const stream = new FicStream(fic, {highWaterMark: 8})
  const externals = {}
  const images = {}
  const chapters = fic.chapters.filter(ch => ch.type !== 'Staff Post')
  const maxConcurrency = 40 // limit saves memory, not network, network is protected elsewhere

  process.emit('debug', `Outputting ${chapters.length} chapters of ${fic.title}`)
  let completed = 0
  let headIndex = 0
  let tailIndex = 0
  function showChapterStatus () {
    progress.show(`Fetching chapters [${completed}/${chapters.length}]`)
  }
  showChapterStatus()
  const finishedChapters = []

  const identifyBuffer = require('buffer-signature').identify
  async function addImage (src, type, filename) {
    if (!src) return
    process.emit('debug', `Outputting ${type} of ${fic.title}`)
    if (/:/.test(src)) {
      fetch.tracker.addWork(1)
      progress.show('Fetching ${type}…')
      try {
        const [meta, imageData] = await fetch(src, {referer: fic.link})
        const info = identifyBuffer(imageData)
        if (filename && !/[.]\w+$/.test(filename) && info.extensions.length) {
          filename += '.' + info.extensions[0]
        }

        const chapter = {
          outputType: type,
          content: imageData,
          mime: info.mimeType
        }
        if (filename) chapter.filename = filename
        await stream.queueChapter(chapter)
      } catch (err) {
        process.emit('error', `Error while fetching ${type} ${src}: ${err.message}`)
      }
    } else {
      await stream.queueChapter({
        outputType: type,
        content: fs.createReadStream(src)
      })
    }
  }

  process.emit('debug', `Considering art`)

  // we return `stream` and this feeds it, so it's intentionally allowed to
  // go off async and not be captured
  Promise.all([addImage(fic.cover, 'cover', 'cover'), addImage(fic.art, 'art', 'art')])
  .then(() => forEach(chapters, async chapterInfo => {
    try {
      const chapter = await chapterInfo.getContent(fetch)

      chapterInfo.order = chapter.order = chapterInfo.type === 'chapter' ? headIndex++ : (8000 + tailIndex ++)
      if (chapterInfo.type !== 'chapter' && !/:/.test(chapter.name)) {
        chapter.name = `${chapterInfo.type}: ${chapterInfo.name}`
      }
      if ((fic.chapterHeadings && chapterInfo.headings !== false) || chapterInfo.headings) {
        const headerName = html`${chapterInfo.name}`
        const byline = !chapterInfo.author ? ''
          : (' by ' + (!chapterInfo.authorUrl ? chapterInfo.author
            : html`<a href="${chapterInfo.authorUrl}">${chapterInfo.author}</a>`))
        const headerLine = `<header><h2>${headerName}${byline}</h2></header>`
        chapter.content = headerLine + chapter.content
      }
      rewriteImages(fic, chapter, inlineImages(images))
      rewriteIframes(fic, chapter)
      chapter.outputType = 'chapter'
      finishedChapters.push({info: chapterInfo, content: chapter})
    } catch (err) {
      process.emit('error', 'Error while fetching chapter', chapterInfo, err.stack)
    } finally {
      ++completed
      showChapterStatus()
    }
  })).then(async () => {
    completed = 0
    showChapterStatus()
    await forEach(finishedChapters, async (chapter, ii) => {
      rewriteLinks(fic, chapter.content, (href, $a) => {
        return linklocalChapters(fic, externals)(href, $a, (href) => {
          if (!chapter.info.externals || !fic.externals) return
          try {
            Site.fromUrl(href)
          } catch (ex) {
            return
          }
          externals[href] = {
            order: 9000 + Object.keys(externals).length,
            num: Object.keys(externals).length + 1,
            requestedBy: chapter.info
          }
          return externalName(externals[href])
        })
      })

      await stream.queueChapter(chapter.content)
      ++completed
      showChapterStatus()
    })

    const externalCount = Object.keys(externals).length
    process.emit('debug', `Outputting ${externalCount} externals of ${fic.title}`)
    fetch.tracker.addWork(externalCount)
    completed = 0
    function showExternalStatus () {
      progress.show(`Fetching externals [${completed}/${externalCount}]`)
    }
    showExternalStatus()
    const pages = externalCount === 1 ? 'page' : 'pages'
    await forEach(Object.keys(externals), maxConcurrency, async (href, exterNum) => {
      const externalInfo = externals[href]
      try {
        const external = await Chapter.getContent(fetch, href)
        external.order = externalInfo.order
        external.num = externalInfo.num
        const name = external.name || external.ficTitle
        let header = ''
        const linkSource = externalInfo.requestedBy.link || externalInfo.requestedBy.fetchFrom
        header += `<div>Linked to from: <a href="${linkSource}">${externalInfo.requestedBy.name}</a></div>`
        const byline = !external.author ? ''
          : (!external.authorUrl ? external.author : html`<a href="${external.authorUrl}">${external.author}</a>`)
        if (name) {
          const headerName = html`${name}`
          header += `<header><h2><a external="false" href="${href}">${headerName}</a>${byline ? ' by ' + byline : ''}</h2></header>`
        } else if (byline) {
          const wrappableLink = href.replace(/(.....)/g, '$1<wbr>')
          header += `<header><h2><div style="font-size: 11px"><a external="false" href="${href}">${wrappableLink}</a></div>`
          header += `by ${byline}</h2></header>`
        }
        external.content = `${header}<hr>${external.content}`
        external.name = exterNum ? null : `External References (${externalCount} ${pages})`
        external.filename = externalName(external)
        external.outputType = 'external'
        rewriteImages(fic, external, inlineImages(images))
        rewriteLinks(fic, external, linklocalChapters(fic, externals))
        rewriteIframes(fic, external)
        await stream.queueChapter(external)
      } catch (err) {
        process.emit('error', `Warning, skipping external ${href}: ${err.stack}`)
        await stream.queueChapter({
          order: 9000 + exterNum,
          name: exterNum ? null : `External References (${externalCount} ${pages})`,
          filename: externalName(externals[href]),
          outputType: 'external',
          content: html`<p>External link to <a href="${href}">${href}</a></p><pre>${err.stack}</pre>`
        })
      } finally {
        ++completed
        showExternalStatus()
      }
    })

    const imageCount = Object.keys(images).length
    fetch.tracker.addWork(imageCount)
    completed = 0
    function showImageStatus () {
      progress.show(`Fetching images [${completed}/${imageCount}]`)
    }
    showImageStatus()
    await forEach(Object.keys(images), maxConcurrency, async (src, imageNum) => {
      try {
        await addImage(src, 'image', images[src].filename)
      } catch (err) {
        process.emit('error', `Error while fetching image ${src}: ${err.message}`)
      } finally {
        ++completed
        showImageStatus()
      }
    })

    process.emit('debug', `Outputting ${fic.title} complete`)
    return stream.queueChapter(null)
  }).catch(err => {
    process.emit('error', `Error in get fic ${err.stack}`)
  })

  return stream
}
<|endoftext|>


<commit_before>const fs = require('fs');
const path = require('path');

function getFileContents(filePath) {
  return fs.readFileSync(filePath, { encoding: 'utf-8' });
}

// Allows you to use short words for Roblox Script classes.
//
// This allows us to use short words to represent Roblox's Script classes. These
// words are commonly used in filenames to identify which file should be created
// as which class in-game.
function getScriptClassFromWord(word) {
  if (word === 'module') {
    return 'ModuleScript';
  } else if (word === 'local') {
    return 'LocalScript';
  } else {
    return 'Script';
  }
}

function luaFileToRobloxObject(filePath) {
  const baseName = path.basename(filePath);
  const parts = baseName.split('.');

  return {
    className: getScriptClassFromWord(parts[1]),
    source: getFileContents(filePath)
  };
}

function handleFile(filePath) {
  if (path.extname(filePath) === '.lua') {
    return luaFileToRobloxObject(filePath);
  };
}

function addChildrenToObjectTree(item, parentNode) {
  const children = fs.readdirSync(item);

  for (let child of children) {
    const fullPath = path.join(item, child);
    pathToRobloxObjectTree(fullPath, parentNode);
  };
}

function pathToRobloxObjectTree(item, parentNode=[]) {
  const stats = fs.statSync(item);
  const name = path.basename(item);
  const nameWithoutExtension = name.split('.');

  var object = { name: nameWithoutExtension };

  if (stats.isDirectory()) {
    Object.assign(object, { children: [] });
    addChildrenToObjectTree(item, object.children)
  } else {
    Object.assign(object, handleFile(item));
  }

  if (object) parentNode.push(object);

  return parentNode;
}

function dirToRobloxObjectTree(dir) {
  const hierarchy = []

  addChildrenToObjectTree(dir, hierarchy)

  return hierarchy
}

module.exports = { dirToRobloxObjectTree }
<commit_msg>Fix the in-game name being an array.<commit_after>const fs = require('fs');
const path = require('path');

function getFileContents(filePath) {
  return fs.readFileSync(filePath, { encoding: 'utf-8' });
}

// Allows you to use short words for Roblox Script classes.
//
// This allows us to use short words to represent Roblox's Script classes. These
// words are commonly used in filenames to identify which file should be created
// as which class in-game.
function getScriptClassFromWord(word) {
  if (word === 'module') {
    return 'ModuleScript';
  } else if (word === 'local') {
    return 'LocalScript';
  } else {
    return 'Script';
  }
}

function luaFileToRobloxObject(filePath) {
  const baseName = path.basename(filePath);
  const parts = baseName.split('.');

  return {
    className: getScriptClassFromWord(parts[1]),
    source: getFileContents(filePath)
  };
}

function handleFile(filePath) {
  if (path.extname(filePath) === '.lua') {
    return luaFileToRobloxObject(filePath);
  };
}

function addChildrenToObjectTree(item, parentNode) {
  const children = fs.readdirSync(item);

  for (let child of children) {
    const fullPath = path.join(item, child);
    pathToRobloxObjectTree(fullPath, parentNode);
  };
}

function pathToRobloxObjectTree(item, parentNode=[]) {
  const stats = fs.statSync(item);
  const filename = path.basename(item);
  const nameParts = filename.split('.');

  var object = { name: nameParts[0] };

  if (stats.isDirectory()) {
    Object.assign(object, { children: [] });
    addChildrenToObjectTree(item, object.children)
  } else {
    Object.assign(object, handleFile(item));
  }

  if (object) parentNode.push(object);

  return parentNode;
}

function dirToRobloxObjectTree(dir) {
  const hierarchy = []

  addChildrenToObjectTree(dir, hierarchy)

  return hierarchy
}

module.exports = { dirToRobloxObjectTree }
<|endoftext|>


<commit_before>var fs        = require("fs")
  , _         = require("underscore")
  , express   = require("express")
  , Resource  = require("express-resource")
  , dnode     = require("dnode")
  , colors    = require('colors')
  , path      = require('path')
  ;

var extractName = require('./libs/utils/namespace').extractName
  , oo = require('./libs/utils/oo');

/******************************************************************************
 * OPTIONS
 */
var USE_UGLIFY_JS = false;

/******************************************************************************
 * CONSTANTS
 */

  /* general dirs */
var MODELS_DIR_NAME        = 'models'
  , VIEWS_DIR_NAME         = 'views'
  , CONTROLLERS_DIR_NAME   = 'controllers'
  , PLUGINS_DIR_NAME       = 'plugins'
  , EXPORT_DIR_NAME        = 'exports'
  , CLIENT_DIR_NAME        = 'client'
  , DATASOURCES_DIR_NAME   = 'datasources'

  /* client specific dirs */
  , CLIENT_LIBS_DIR = path.join(CLIENT_DIR_NAME, 'libs')
  , CLIENT_STATIC_DIR = path.join(CLIENT_DIR_NAME, 'static')

  /* namespace constants */
  , CONTROLLER_SUFFIX = '_controller'
  ;

/******************************************************************************
 * GLOBALS
 */

var missing = [];

/******************************************************************************
 * Controllers Setup
 */
function setupControllers(app) {
  /**
   * @param name String = name of the Controller
   * @param method String = name of the Method
   * @param has_view Bool = true if this Controller's Method has that view
   *
   * Builds a wrapper function sending raw json as a response if no view is found
   * or a rendered view
   */

  var top_dir = app._rocket.app_dir;

  function buildWrapper(name, method, has_view, dir) {
    return function(req, res) {
      var methods = require(path.join(dir, CONTROLLERS_DIR_NAME, name + CONTROLLER_SUFFIX));

      if(!req.xhr && has_view) {
        var oSend = res.send;
        res.send = function(obj) {
          obj = obj || {};

          res.send = oSend;

          res.render(path.join(dir, VIEWS_DIR_NAME, name,  [name, method, 'jade'].join('.') ), _.extend(obj, {controller: name}) );
        };
      }
      methods[method](req, res);
    };
  }

  /**
   * @param name String = name of the Controller
   * @param has_view Bool = true if the controller has a matching view
   *
   * Uses information from searchFolders to add the controller URL
   * to the app, introduces a wrapping function around these controller
   * calls.
   */
  function setController(name, has_view, dir) {
    var wrapped_funcs = {}
      , view_methods_files = []
      , view_methods = []
      , split = []
      , controller_methods = _.functions(require(path.join(dir, CONTROLLERS_DIR_NAME, name + CONTROLLER_SUFFIX)))
      ;

    if (app._rocket.routes.indexOf(name) !== -1) {
      throw("Route already in use");
    }

    if (has_view) {
      // Get the methods for which views exist
      view_methods_files = fs.readdirSync(path.join(dir, VIEWS_DIR_NAME, name));

      for(var i = 0; i < view_methods_files.length; i++) {
        split = view_methods_files[i].split('.');
        if(split[0] === name) {
          view_methods.push(split[split.length - 2]);
        }
      }
    }

    for(var i = 0; i < controller_methods.length; i++) {
      var method_view = false;

      if(view_methods.indexOf(controller_methods[i]) !== -1) {
        method_view = true;
      }

      wrapped_funcs[controller_methods[i]] = buildWrapper(name, controller_methods[i], method_view, dir);
    }

    if (name === 'root') {
      app.resource(wrapped_funcs);
    } else {
      app.resource(name, wrapped_funcs);
    }
  }

  /**
   * Gets the name of each controller and searches through the view folder
   * to see wether it finds a corresponding view
   */
  function searchFolders(dir) {
    var controllers = []
      , views = []
      , has_view = false
      , split = []
      ;

    try{
      controllers = fs.readdirSync(path.join(dir, CONTROLLERS_DIR_NAME));
    }catch(err){
      if(err.code === 'ENOENT') {
        console.log(('!!! WARNING No `' + CONTROLLERS_DIR_NAME + '` dir found in [' + dir + ']. Skipping exports...').yellow);
      }else{
        throw(err);
      }
    }

    try{
      views = fs.readdirSync(path.join(dir, VIEWS_DIR_NAME));
    }catch(err){
      if(err.code === 'ENOENT') {
        console.log(('!!! WARNING No `' + VIEWS_DIR_NAME + '` dir found in [' + dir + ']. Skipping exports...').yellow);
      }else{
        throw(err);
      }
    }

    for(var i = 0; i < views.length; i++) {
      views[i] = extractName(views[i]);
    }

    for(var i = 0; i < controllers.length; i++) {

      //Gets dir/name.controller.js and returns name
      var controller = extractName( controllers[i]
                                  , {extension: true , suffix: CONTROLLER_SUFFIX}
                                  );

      if(views.indexOf(controller) !== -1) { has_view = true; }

      setController(controller, has_view, dir);
    }
  }

  /**
   * This function starts the controller set up, setting the main controllers and
   * views then running through the plugin dirs
   */
  function init() {

    var plugins = {};

    try{
      plugins = fs.readdirSync(path.join(top_dir, PLUGINS_DIR_NAME));
    }catch(err){
        if(err.code === 'ENOENT') {
          console.log('!!! WARNING No `plugins` dir found in project. Skipping plugins...'.yellow);
          missing.push(PLUGINS_DIR_NAME);
        }else{
          throw(err);
        }
    }

    searchFolders(top_dir);

    for(var i = 0; i < plugins.length; i++) {
      searchFolders(path.join(top_dir, PLUGINS_DIR_NAME, plugins[i]));
    }

  }

  init();
}

/******************************************************************************
 * Models Setup
 */
function setupModels(app) {
  var models_files = fs.readdirSync(path.join(app._rocket.app_dir, MODELS_DIR_NAME));

  for(var i = 0; i < models_files.length; i++) {
    if(models_files[i] === DATASOURCES_DIR_NAME) {
      continue;
    }
    var myModel = require(path.join(app._rocket.app_dir, MODELS_DIR_NAME, models_files[i]));
    myModel.initialize();
  }
}

/******************************************************************************
 * Compile exports
 */
function compileExports(app) {
  var dirs
    , plugins
    , exported_dirs = {'': path.join(app._rocket.app_dir, EXPORT_DIR_NAME)}
    , myExports = {};

  // Add plugin exports to EXPORT_DIRS
  if(missing.indexOf(PLUGINS_DIR_NAME) === -1){
    try{
      plugins = fs.readdirSync(path.join(app._rocket.app_dir, PLUGINS_DIR_NAME));
      for(var i = 0; i < plugins.length; i++) {
        exported_dirs[plugins[i]] = path.join(app._rocket.app_dir, PLUGINS_DIR_NAME, plugins[i], EXPORT_DIR_NAME);
      }
    }catch(err){
      if(err.code == 'ENOENT') {
            console.log('!!! WARNING No `plugins` dir found in project. Skipping plugin exports...'.yellow);
            missing.push(PLUGINS_DIR_NAME);
      }else{
        throw(err);
      }
    }
  }

  for(var export_name in exported_dirs) {
    var container;

    if(export_name === '') {
      container = myExports;
    }else{
      myExports[export_name] = {};
      container = myExports[export_name];
    }

    try{
      dirs = fs.readdirSync(exported_dirs[export_name]);

      for (var j = 0; j < dirs.length; j++) {
        var objName = dirs[j].split(".")[0]
          , obj = require(exported_dirs[export_name] + dirs[j]);

          container[objName] = obj;
      }
    }catch(err){
      if(err.code === 'ENOENT') {
        console.log('!!! WARNING No `exports` dir found in project. Skipping exports...'.yellow);
        missing.push(EXPORT_DIR_NAME);
      }else{
        throw(err);
      }
    }
  }

  if(myExports.length > 0) {
    app._rocket.dnode = dnode(myExports);
  }

}

/******************************************************************************
 * UTILITY FUNCTIONS
 */
function uglifyFilter(orig_code) {
  var jsp = require("uglify-js").parser
    , pro = require("uglify-js").uglify
    , ast = jsp.parse(orig_code); // parse code and get the initial AST

  ast = pro.ast_mangle(ast);      // get a new AST with mangled names
  ast = pro.ast_squeeze(ast);     // get an AST with compression optimizations
  return pro.gen_code(ast);       // compressed code here
};

/******************************************************************************
 * EXPORTS
 */
var package_JSON = fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8');
var package_info = JSON.parse(package_JSON);

var rocket = {
    version: package_info.version
  , resources: require('./libs/resources')
  , utils: require('./libs/utils')
  , createServer: function createServer_rocket(app_dir) {
      var app = express.createServer();

      app._rocket = {};
      app._rocket.routes = [];

      app._rocket.app_dir = app_dir;

      //replace listen on app
      var express_listen = app.listen;
      app.listen = function () {
        var ret = express_listen.apply(this, arguments);
        if(missing.indexOf(EXPORT_DIR_NAME) === -1 ) {
          app._rocket.dnode.listen(app);
        }
        return ret;
      }

      //default configuration
      app.configure(function() {
        app.set("view engine", 'jade');
        app.set("views", path.join(app._rocket.app_dir, VIEWS_DIR_NAME));
        app.register(".jade",require('jade'));

        app.use(express.methodOverride());

        app.use('/static', express.static(path.join(app._rocket.app_dir, CLIENT_STATIC_DIR)));
        app.use(express.bodyParser());
        app.use(require('browserify')({
          base : [path.join(app._rocket.app_dir, CLIENT_LIBS_DIR)/*, path.join(app._rocket.app_dir, PLUGINS_DIR_NAME, 'test', 'client', 'libs')*/],
          mount : '/browserify.js',
          filter:  (USE_UGLIFY_JS ? uglifyFilter : undefined),
          require: ['dnode']
          }));
      });

      //setup controllers
      setupControllers(app);

      //setup models
      setupModels(app);

      //compile exports
      compileExports(app);

      return app;

    }
};

oo.__extends(rocket, express);
module.exports = rocket;<commit_msg>Modified browserify inptu to be an array<commit_after>var fs        = require("fs")
  , _         = require("underscore")
  , express   = require("express")
  , Resource  = require("express-resource")
  , dnode     = require("dnode")
  , colors    = require('colors')
  , path      = require('path')
  ;

var extractName = require('./libs/utils/namespace').extractName
  , oo = require('./libs/utils/oo');

/******************************************************************************
 * OPTIONS
 */
var USE_UGLIFY_JS = false;

/******************************************************************************
 * CONSTANTS
 */

  /* general dirs */
var MODELS_DIR_NAME        = 'models'
  , VIEWS_DIR_NAME         = 'views'
  , CONTROLLERS_DIR_NAME   = 'controllers'
  , PLUGINS_DIR_NAME       = 'plugins'
  , EXPORT_DIR_NAME        = 'exports'
  , CLIENT_DIR_NAME        = 'client'
  , DATASOURCES_DIR_NAME   = 'datasources'

  /* client specific dirs */
  , CLIENT_LIBS_DIR = path.join(CLIENT_DIR_NAME, 'libs')
  , CLIENT_STATIC_DIR = path.join(CLIENT_DIR_NAME, 'static')

  /* namespace constants */
  , CONTROLLER_SUFFIX = '_controller'
  ;

/******************************************************************************
 * GLOBALS
 */

var missing = [];

/******************************************************************************
 * Controllers Setup
 */
function setupControllers(app) {
  /**
   * @param name String = name of the Controller
   * @param method String = name of the Method
   * @param has_view Bool = true if this Controller's Method has that view
   *
   * Builds a wrapper function sending raw json as a response if no view is found
   * or a rendered view
   */

  var top_dir = app._rocket.app_dir;

  function buildWrapper(name, method, has_view, dir) {
    return function(req, res) {
      var methods = require(path.join(dir, CONTROLLERS_DIR_NAME, name + CONTROLLER_SUFFIX));

      if(!req.xhr && has_view) {
        var oSend = res.send;
        res.send = function(obj) {
          obj = obj || {};

          res.send = oSend;

          res.render(path.join(dir, VIEWS_DIR_NAME, name,  [name, method, 'jade'].join('.') ), _.extend(obj, {controller: name}) );
        };
      }
      methods[method](req, res);
    };
  }

  /**
   * @param name String = name of the Controller
   * @param has_view Bool = true if the controller has a matching view
   *
   * Uses information from searchFolders to add the controller URL
   * to the app, introduces a wrapping function around these controller
   * calls.
   */
  function setController(name, has_view, dir) {
    var wrapped_funcs = {}
      , view_methods_files = []
      , view_methods = []
      , split = []
      , controller_methods = _.functions(require(path.join(dir, CONTROLLERS_DIR_NAME, name + CONTROLLER_SUFFIX)))
      ;

    if (app._rocket.routes.indexOf(name) !== -1) {
      throw("Route already in use");
    }

    if (has_view) {
      // Get the methods for which views exist
      view_methods_files = fs.readdirSync(path.join(dir, VIEWS_DIR_NAME, name));

      for(var i = 0; i < view_methods_files.length; i++) {
        split = view_methods_files[i].split('.');
        if(split[0] === name) {
          view_methods.push(split[split.length - 2]);
        }
      }
    }

    for(var i = 0; i < controller_methods.length; i++) {
      var method_view = false;

      if(view_methods.indexOf(controller_methods[i]) !== -1) {
        method_view = true;
      }

      wrapped_funcs[controller_methods[i]] = buildWrapper(name, controller_methods[i], method_view, dir);
    }

    if (name === 'root') {
      app.resource(wrapped_funcs);
    } else {
      app.resource(name, wrapped_funcs);
    }
  }

  /**
   * Gets the name of each controller and searches through the view folder
   * to see wether it finds a corresponding view
   */
  function searchFolders(dir) {
    var controllers = []
      , views = []
      , has_view = false
      , split = []
      ;

    try{
      controllers = fs.readdirSync(path.join(dir, CONTROLLERS_DIR_NAME));
    }catch(err){
      if(err.code === 'ENOENT') {
        console.log(('!!! WARNING No `' + CONTROLLERS_DIR_NAME + '` dir found in [' + dir + ']. Skipping exports...').yellow);
      }else{
        throw(err);
      }
    }

    try{
      views = fs.readdirSync(path.join(dir, VIEWS_DIR_NAME));
    }catch(err){
      if(err.code === 'ENOENT') {
        console.log(('!!! WARNING No `' + VIEWS_DIR_NAME + '` dir found in [' + dir + ']. Skipping exports...').yellow);
      }else{
        throw(err);
      }
    }

    for(var i = 0; i < views.length; i++) {
      views[i] = extractName(views[i]);
    }

    for(var i = 0; i < controllers.length; i++) {

      //Gets dir/name.controller.js and returns name
      var controller = extractName( controllers[i]
                                  , {extension: true , suffix: CONTROLLER_SUFFIX}
                                  );

      if(views.indexOf(controller) !== -1) { has_view = true; }

      setController(controller, has_view, dir);
    }
  }

  /**
   * This function starts the controller set up, setting the main controllers and
   * views then running through the plugin dirs
   */
  function init() {

    var plugins = {};

    try{
      plugins = fs.readdirSync(path.join(top_dir, PLUGINS_DIR_NAME));
    }catch(err){
        if(err.code === 'ENOENT') {
          console.log('!!! WARNING No `plugins` dir found in project. Skipping plugins...'.yellow);
          missing.push(PLUGINS_DIR_NAME);
        }else{
          throw(err);
        }
    }

    searchFolders(top_dir);

    for(var i = 0; i < plugins.length; i++) {
      searchFolders(path.join(top_dir, PLUGINS_DIR_NAME, plugins[i]));
    }

  }

  init();
}

/******************************************************************************
 * Models Setup
 */
function setupModels(app) {
  var models_files = fs.readdirSync(path.join(app._rocket.app_dir, MODELS_DIR_NAME));

  for(var i = 0; i < models_files.length; i++) {
    if(models_files[i] === DATASOURCES_DIR_NAME) {
      continue;
    }
    var myModel = require(path.join(app._rocket.app_dir, MODELS_DIR_NAME, models_files[i]));
    myModel.initialize();
  }
}

/******************************************************************************
 * Compile exports
 */
function compileExports(app) {
  var dirs
    , plugins
    , exported_dirs = {'': path.join(app._rocket.app_dir, EXPORT_DIR_NAME)}
    , myExports = {};

  // Add plugin exports to EXPORT_DIRS
  if(missing.indexOf(PLUGINS_DIR_NAME) === -1){
    try{
      plugins = fs.readdirSync(path.join(app._rocket.app_dir, PLUGINS_DIR_NAME));
      for(var i = 0; i < plugins.length; i++) {
        exported_dirs[plugins[i]] = path.join(app._rocket.app_dir, PLUGINS_DIR_NAME, plugins[i], EXPORT_DIR_NAME);
      }
    }catch(err){
      if(err.code == 'ENOENT') {
            console.log('!!! WARNING No `plugins` dir found in project. Skipping plugin exports...'.yellow);
            missing.push(PLUGINS_DIR_NAME);
      }else{
        throw(err);
      }
    }
  }

  for(var export_name in exported_dirs) {
    var container;

    if(export_name === '') {
      container = myExports;
    }else{
      myExports[export_name] = {};
      container = myExports[export_name];
    }

    try{
      dirs = fs.readdirSync(exported_dirs[export_name]);

      for (var j = 0; j < dirs.length; j++) {
        var objName = dirs[j].split(".")[0]
          , obj = require(exported_dirs[export_name] + dirs[j]);

          container[objName] = obj;
      }
    }catch(err){
      if(err.code === 'ENOENT') {
        console.log('!!! WARNING No `exports` dir found in project. Skipping exports...'.yellow);
        missing.push(EXPORT_DIR_NAME);
      }else{
        throw(err);
      }
    }
  }

  if(myExports.length > 0) {
    app._rocket.dnode = dnode(myExports);
  }

}

/******************************************************************************
 * UTILITY FUNCTIONS
 */
function uglifyFilter(orig_code) {
  var jsp = require("uglify-js").parser
    , pro = require("uglify-js").uglify
    , ast = jsp.parse(orig_code); // parse code and get the initial AST

  ast = pro.ast_mangle(ast);      // get a new AST with mangled names
  ast = pro.ast_squeeze(ast);     // get an AST with compression optimizations
  return pro.gen_code(ast);       // compressed code here
};

/******************************************************************************
 * EXPORTS
 */
var package_JSON = fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8');
var package_info = JSON.parse(package_JSON);

var rocket = {
    version: package_info.version
  , resources: require('./libs/resources')
  , utils: require('./libs/utils')
  , createServer: function createServer_rocket(app_dir) {
      var app = express.createServer();

      app._rocket = {};
      app._rocket.routes = [];

      app._rocket.app_dir = app_dir;

      //replace listen on app
      var express_listen = app.listen;
      app.listen = function () {
        var ret = express_listen.apply(this, arguments);
        if(missing.indexOf(EXPORT_DIR_NAME) === -1 ) {
          app._rocket.dnode.listen(app);
        }
        return ret;
      }

      //default configuration
      app.configure(function() {
        app.set("view engine", 'jade');
        app.set("views", path.join(app._rocket.app_dir, VIEWS_DIR_NAME));
        app.register(".jade",require('jade'));

        app.use(express.methodOverride());

        app.use('/static', express.static(path.join(app._rocket.app_dir, CLIENT_STATIC_DIR)));
        app.use(express.bodyParser());
        app.use(require('browserify')({
            base : [path.join(app._rocket.app_dir, CLIENT_LIBS_DIR)]
          , mount : '/browserify.js'
          , filter:  (USE_UGLIFY_JS ? uglifyFilter : undefined)
          , require: ['dnode']
          }));
      });

      //setup controllers
      setupControllers(app);

      //setup models
      setupModels(app);

      //compile exports
      compileExports(app);

      return app;

    }
};

oo.__extends(rocket, express);
module.exports = rocket;<|endoftext|>