<commit_before>// ==UserScript==
// @name         NoMouse
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Keyboard FP browsing
// @author       You
// @match        https://facepunch.com/*
// @grant        none
// ==/UserScript==
//(function() {
//    'use strict';
//
//    // Your code here...
//})();

// v Edit here v
var HotForum1 = "";
var HotForum2 = "";
var HotForum3 = "";
var HotForum4 = "";
var HotForum5 = "";

var SelectionColor = "red";
var SelectionPrefix = ">";
var SelectionPostfix = "<";
// ^ Edit here ^

// Locations
var Punch = "https://facepunch.com/";
var ShowThread = "showthread.php";
var ForumDisplay = "forumdisplay.php";
var MainForum = "forum.php";
var Subscribed = "usercp.php";

// Navigation
var Exit = $(".navbit a");
var Pages = $('.pagination_top a');
var PagesThread = $('.threadpagenav a');

// Thread
var CurrenPost = 0;
var Posts = $(".postbitlegacy");
var PostsMax = Posts.length;

// Threads
var Threads = $('a[id*="thread_title_"]');
var CurrentThread = 0;
var MaxThreads = Threads.length;

// Forums
var Forums = $(".forums tr .forumtitle a");
var CurrentForum = 0;
var MaxForums = Forums.length;
var Typing = false;

function PageScroll(ID) {
    $('html, body').animate({
        'scrollTop': $('#' + ID).offset().top
    }, 200);
}

function PageLoad(Page) {
    window.location = Punch + Page;
}

function PageCheck(Page) {
    if (window.location.href.indexOf(Page) != -1) {
        return true;
    }
    else
    {
        return false;
    }
}

$(document).ready(function() {
    console.log(Typing);
    if (PageCheck(ShowThread)) {
        console.log(location.hash);
        if (location.hash !== "") {
            $(Posts).each(function(index) {
                if ($(this).attr('id') == location.hash.replace("#post", "post_")) {
                    CurrenPost = index;

                }
                console.log(CurrenPost+" "+index+" "+$(this).attr('id')+" "+location.hash.replace("#post", "post_"));
            });
        }
        PageScroll($(Posts[CurrenPost]).attr('id'));
    }
    if (PageCheck(ForumDisplay)||PageCheck(Subscribed)) {
        $('a[href="' + $(Threads[CurrentThread]).attr("href") + '"]').css("color", SelectionColor);
        $('a[href="' + $(Threads[CurrentThread]).attr("href") + '"]').prepend(''+SelectionPrefix+' </span').append(' '+SelectionPostfix+'</span');
    }
    $('a[href="' + $(Forums[CurrentForum]).attr("href") + '"]').css("color", SelectionColor);
    $('a[href="' + $(Forums[CurrentForum]).attr("href") + '"]').prepend(''+SelectionPrefix+' </span').append(' '+SelectionPostfix+'</span');
});

$(function() {

    $(window).keypress(function(e) {
        var key = e.which;
        console.log(key);
        if (PageCheck(ShowThread)) {
            if (document.activeElement.value !== undefined) {
                Typing = true;
            }
            else
            {
                Typing = false;
            }
        }

        // Unified scroller
        var PositionCurrent;
        var PositionMax;
        var IDList;

        if (PageCheck(ShowThread)) {
            if($('.updatemenu')!== undefined)
            {
                Posts = $(".postbitlegacy");
                PostsMax = Posts.length;
                Pages = $('.pagination_top a');
            }

            PositionCurrent = CurrenPost;
            PositionMax = PostsMax;
            IDList = Posts;

        }

        if (PageCheck(MainForum)) {
            PositionCurrent = CurrentForum;
            PositionMax = MaxForums;
            IDList = Forums;
            $('a[href="' + $(Forums[CurrentForum]).attr("href") + '"]').css("color", "");
            $('.prepended').remove();
        }

        if (PageCheck(ForumDisplay)||PageCheck(Subscribed)) {
            PositionCurrent = CurrentThread;
            PositionMax = MaxThreads;
            IDList = Threads;
            $('a[href="' + $(Threads[CurrentThread]).attr("href") + '"]').css("color", "");
            $('.prepended').remove();
        }

        if (Typing == false)
        {
            if (PageCheck(ForumDisplay) || PageCheck(MainForum) || PageCheck(ShowThread)||PageCheck(Subscribed)) {
                console.log(Typing);
                switch (key) {
                        // S
                    case 115:
                        PositionCurrent++;
                        if (PositionCurrent >= PositionMax) {
                            PositionCurrent = 0;
                        }
                        break;
                        // W
                    case 119:
                        PositionCurrent--;
                        if (PositionCurrent < 0) {
                            PositionCurrent = PositionMax - 1;
                        }
                        break;
                        // E
                    case 101:
                        if (PageCheck(ForumDisplay) || PageCheck(MainForum)||PageCheck(Subscribed))
                        {
                            PageLoad($(IDList[PositionCurrent]).attr("href"));
                        }
                        if (PageCheck(ShowThread))
                        {

                            PageLoad($(IDList[PositionCurrent]).find('.postcontrols a').attr("href"));
                        }

                        break;
                        // N
                    case 110:
                        if (PageCheck(ForumDisplay)||PageCheck(Subscribed))
                        {
                            PageLoad($(IDList[PositionCurrent]).attr("href") + "&goto=newpost");
                        }
                        if (PageCheck(ShowThread))
                        {
                            $(IDList).each(function(index) {
                                if ($(this).attr('id') == $(".postbitnew").attr("id")) {
                                    PositionCurrent = index;
                                }
                            });
                        }
                        break;
                }
            }
        }

        if (PageCheck(ShowThread)||PageCheck(ForumDisplay)||PageCheck(Subscribed)) {
            CurrenPost = PositionCurrent;
            PostsMax = PositionMax;

            if (key == 115 || key == 119 || key == 110) {
                PageScroll($(IDList[PositionCurrent]).attr('id'));
            }
        }
        if (PageCheck(MainForum)) {
            CurrentForum = PositionCurrent;
            MaxForums = PositionMax;
            $('a[href="' + $(Forums[CurrentForum]).attr("href") + '"]').css("color", SelectionColor);
            $('a[href="' + $(Forums[CurrentForum]).attr("href") + '"]').prepend(''+SelectionPrefix+' </span').append(' '+SelectionPostfix+'</span');
        }
        if (PageCheck(ForumDisplay)||PageCheck(Subscribed)) {
            CurrentThread = PositionCurrent;
            MaxThreads = PositionMax;
            $('a[href="' + $(Threads[CurrentThread]).attr("href") + '"]').css("color", SelectionColor);
            $('a[href="' + $(Threads[CurrentThread]).attr("href") + '"]').prepend('>'+SelectionPrefix+' </span').append(' '+SelectionPostfix+'</span');
        }

        if (PageCheck(ForumDisplay))
        {
            Pages = PagesThread;
        }

        if ( PageCheck("newthread.php") == false && PageCheck("newreply.php") == false) {
            switch (key) {
                    // D
                case 100:
                    $(Pages).each(function(index) {
                        if ($(this).attr('title').indexOf("Next Page") != -1) {
                            PageLoad($(this).attr('href'));
                        }
                    });
                    break;
                    // A
                case 97:
                    $(Pages).each(function(index) {
                        if ($(this).attr('title').indexOf("Prev Page") != -1) {
                            PageLoad($(this).attr('href'));
                        }
                    });
                    break;
                    // Z
                case 122:
                    $(Pages).each(function(index) {
                        if ($(this).attr('title').indexOf("First Page") != -1) {
                            PageLoad($(this).attr('href'));
                        }
                    });
                    break;
                    // X
                case 120:
                    $(Pages).each(function(index) {
                        if ($(this).attr('title').indexOf("Last Page") != -1) {
                            PageLoad($(this).attr('href'));
                        }
                    });
                    break;
                    // 1
                case 49:
                    PageLoad("usercp.php");
                    break;
                    // 2
                case 50:
                    PageLoad("fp_events.php");
                    break;
                    // 3
                case 51:
                    PageLoad("fp_popular.php");
                    break;
                    // 4
                case 52:
                    PageLoad("fp_read.php");
                    break;
                    // 5
                case 53:
                    PageLoad("search.php");
                    break;
                    // 6
                case 53:
                    PageLoad(HotForum1);
                    break;
                    // 7
                case 53:
                    PageLoad(HotForum2);
                    break;
                    // 8
                case 53:
                    PageLoad(HotForum3);
                    break;
                    // 9
                case 53:
                    PageLoad(HotForum4);
                    break;
                    // 0
                case 53:
                    PageLoad(HotForum5);
                    break;
                    // Q
                case 113:
                    if ($(Exit[Exit.length - 1]).attr("href")!==undefined)
                    {
                        PageLoad($(Exit[Exit.length - 1]).attr("href"));
                    }
                    else
                    {
                        PageLoad("forum.php");
                    }
                    break;
            }
        }
    });
});
<commit_msg>Update NoMouse.user.js<commit_after>// ==UserScript==
// @name         NoMouse
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Keyboard FP browsing
// @author       You
// @match        https://facepunch.com/*
// @grant        none
// ==/UserScript==
//(function() {
//    'use strict';
//
//    // Your code here...
//})();

// v Edit here v
var HotForum1 = "";
var HotForum2 = "";
var HotForum3 = "";
var HotForum4 = "";
var HotForum5 = "";

var SelectionColor = "red";
var SelectionPrefix = ">";
var SelectionPostfix = "<";
// ^ Edit here ^

// Locations
var Punch = "https://facepunch.com/";
var ShowThread = "showthread.php";
var ForumDisplay = "forumdisplay.php";
var MainForum = "forum.php";
var Subscribed = "usercp.php";

// Navigation
var Exit = $(".navbit a");
var Pages = $('.pagination_top a');
var PagesThread = $('.threadpagenav a');

// Thread
var CurrenPost = 0;
var Posts = $(".postbitlegacy");
var PostsMax = Posts.length;

// Threads
var Threads = $('a[id*="thread_title_"]');
var CurrentThread = 0;
var MaxThreads = Threads.length;

// Forums
var Forums = $(".forums tr .forumtitle a");
var CurrentForum = 0;
var MaxForums = Forums.length;
var Typing = false;

function PageScroll(ID) {
    $('html, body').animate({
        'scrollTop': $('#' + ID).offset().top
    }, 200);
}

function PageLoad(Page) {
    window.location = Punch + Page;
}

function PageCheck(Page) {
    if (window.location.href.indexOf(Page) != -1) {
        return true;
    }
    else
    {
        return false;
    }
}

$(document).ready(function() {
    console.log(Typing);
    if (PageCheck(ShowThread)) {
        console.log(location.hash);
        if (location.hash !== "") {
            $(Posts).each(function(index) {
                if ($(this).attr('id') == location.hash.replace("#post", "post_")) {
                    CurrenPost = index;

                }
                console.log(CurrenPost+" "+index+" "+$(this).attr('id')+" "+location.hash.replace("#post", "post_"));
            });
        }
        PageScroll($(Posts[CurrenPost]).attr('id'));
    }
    if (PageCheck(ForumDisplay)||PageCheck(Subscribed)) {
        $('a[href="' + $(Threads[CurrentThread]).attr("href") + '"]').css("color", SelectionColor);
        $('a[href="' + $(Threads[CurrentThread]).attr("href") + '"]').prepend(''+SelectionPrefix+' </span').append(' '+SelectionPostfix+'</span');
    }
    $('a[href="' + $(Forums[CurrentForum]).attr("href") + '"]').css("color", SelectionColor);
    $('a[href="' + $(Forums[CurrentForum]).attr("href") + '"]').prepend(''+SelectionPrefix+' </span').append(' '+SelectionPostfix+'</span');
});

$(function() {

    $(window).keypress(function(e) {
        var key = e.which;
        console.log(key);
        if (PageCheck(ShowThread)) {
            if (document.activeElement.value !== undefined) {
                Typing = true;
            }
            else
            {
                Typing = false;
            }
        }

        // Unified scroller
        var PositionCurrent;
        var PositionMax;
        var IDList;

        if (PageCheck(ShowThread)) {
            if($('.updatemenu')!== undefined)
            {
                Posts = $(".postbitlegacy");
                PostsMax = Posts.length;
                Pages = $('.pagination_top a');
            }

            PositionCurrent = CurrenPost;
            PositionMax = PostsMax;
            IDList = Posts;

        }

        if (PageCheck(MainForum)) {
            PositionCurrent = CurrentForum;
            PositionMax = MaxForums;
            IDList = Forums;
            $('a[href="' + $(Forums[CurrentForum]).attr("href") + '"]').css("color", "");
            $('.prepended').remove();
        }

        if (PageCheck(ForumDisplay)||PageCheck(Subscribed)) {
            PositionCurrent = CurrentThread;
            PositionMax = MaxThreads;
            IDList = Threads;
            $('a[href="' + $(Threads[CurrentThread]).attr("href") + '"]').css("color", "");
            $('.prepended').remove();
        }

        if (Typing == false)
        {
            if (PageCheck(ForumDisplay) || PageCheck(MainForum) || PageCheck(ShowThread)||PageCheck(Subscribed)) {
                console.log(Typing);
                switch (key) {
                        // S
                    case 115:
                        PositionCurrent++;
                        if (PositionCurrent >= PositionMax) {
                            PositionCurrent = 0;
                        }
                        break;
                        // W
                    case 119:
                        PositionCurrent--;
                        if (PositionCurrent < 0) {
                            PositionCurrent = PositionMax - 1;
                        }
                        break;
                        // E
                    case 101:
                        if (PageCheck(ForumDisplay) || PageCheck(MainForum)||PageCheck(Subscribed))
                        {
                            PageLoad($(IDList[PositionCurrent]).attr("href"));
                        }
                        if (PageCheck(ShowThread))
                        {

                            PageLoad($(IDList[PositionCurrent]).find('.postcontrols a').attr("href"));
                        }

                        break;
                        // N
                    case 110:
                        if (PageCheck(ForumDisplay)||PageCheck(Subscribed))
                        {
                            PageLoad($(IDList[PositionCurrent]).attr("href") + "&goto=newpost");
                        }
                        if (PageCheck(ShowThread))
                        {
                            $(IDList).each(function(index) {
                                if ($(this).attr('id') == $(".postbitnew").attr("id")) {
                                    PositionCurrent = index;
                                }
                            });
                        }
                        break;
                }
            }
        }

        if (PageCheck(ShowThread)||PageCheck(ForumDisplay)||PageCheck(Subscribed)) {
            CurrenPost = PositionCurrent;
            PostsMax = PositionMax;

            if (key == 115 || key == 119 || key == 110) {
                PageScroll($(IDList[PositionCurrent]).attr('id'));
            }
        }
        if (PageCheck(MainForum)) {
            CurrentForum = PositionCurrent;
            MaxForums = PositionMax;
            $('a[href="' + $(Forums[CurrentForum]).attr("href") + '"]').css("color", SelectionColor);
            $('a[href="' + $(Forums[CurrentForum]).attr("href") + '"]').prepend(''+SelectionPrefix+' </span').append(' '+SelectionPostfix+'</span');
        }
        if (PageCheck(ForumDisplay)||PageCheck(Subscribed)) {
            CurrentThread = PositionCurrent;
            MaxThreads = PositionMax;
            $('a[href="' + $(Threads[CurrentThread]).attr("href") + '"]').css("color", SelectionColor);
            $('a[href="' + $(Threads[CurrentThread]).attr("href") + '"]').prepend(''+SelectionPrefix+' </span').append(' '+SelectionPostfix+'</span');
        }

        if (PageCheck(ForumDisplay))
        {
            Pages = PagesThread;
        }

        if ( PageCheck("newthread.php") == false && PageCheck("newreply.php") == false) {
            switch (key) {
                    // D
                case 100:
                    $(Pages).each(function(index) {
                        if ($(this).attr('title').indexOf("Next Page") != -1) {
                            PageLoad($(this).attr('href'));
                        }
                    });
                    break;
                    // A
                case 97:
                    $(Pages).each(function(index) {
                        if ($(this).attr('title').indexOf("Prev Page") != -1) {
                            PageLoad($(this).attr('href'));
                        }
                    });
                    break;
                    // Z
                case 122:
                    $(Pages).each(function(index) {
                        if ($(this).attr('title').indexOf("First Page") != -1) {
                            PageLoad($(this).attr('href'));
                        }
                    });
                    break;
                    // X
                case 120:
                    $(Pages).each(function(index) {
                        if ($(this).attr('title').indexOf("Last Page") != -1) {
                            PageLoad($(this).attr('href'));
                        }
                    });
                    break;
                    // 1
                case 49:
                    PageLoad("usercp.php");
                    break;
                    // 2
                case 50:
                    PageLoad("fp_events.php");
                    break;
                    // 3
                case 51:
                    PageLoad("fp_popular.php");
                    break;
                    // 4
                case 52:
                    PageLoad("fp_read.php");
                    break;
                    // 5
                case 53:
                    PageLoad("search.php");
                    break;
                    // 6
                case 53:
                    PageLoad(HotForum1);
                    break;
                    // 7
                case 53:
                    PageLoad(HotForum2);
                    break;
                    // 8
                case 53:
                    PageLoad(HotForum3);
                    break;
                    // 9
                case 53:
                    PageLoad(HotForum4);
                    break;
                    // 0
                case 53:
                    PageLoad(HotForum5);
                    break;
                    // Q
                case 113:
                    if ($(Exit[Exit.length - 1]).attr("href")!==undefined)
                    {
                        PageLoad($(Exit[Exit.length - 1]).attr("href"));
                    }
                    else
                    {
                        PageLoad("forum.php");
                    }
                    break;
            }
        }
    });
});
<|endoftext|>


<commit_before>// @flow
import {error, HELP_IDS, warning} from '../createValidationResult'
import inspect from '../../inspect'

const VALID_FIELD_RE = /^[A-Za-z]+[0-9A-Za-z_\s-]*$/
const CONVENTIONAL_FIELD_RE = /^[A-Za-z_]+[0-9A-Za-z_]*$/

function validateFieldName(name): Array<any> {
  if (typeof name !== 'string') {
    return [
      error(
        `Field names must be strings. Saw "${inspect(name)}"`,
        HELP_IDS.OBJECT_FIELD_NAME_INVALID
      )
    ]
  }
  if (name.startsWith('_')) {
    return [
      error(
        `Invalid field name "${name}". Field names cannot start with underscores "_" as it's reserved for system fields.`,
        HELP_IDS.OBJECT_FIELD_NAME_INVALID
      )
    ]
  }

  if (!VALID_FIELD_RE.test(name)) {
    return [
      error(
        `Invalid field name: ${name}. Fields can only contain characters from a-z, numbers and underscores and should not start with a number (${String(
          VALID_FIELD_RE
        )})`,
        HELP_IDS.OBJECT_FIELD_NAME_INVALID
      )
    ]
  }
  if (!CONVENTIONAL_FIELD_RE.test(name)) {
    return [
      warning(
        'Thats an interesting field name for sure! But it is... how to put it... a bit... unconventional?' +
          ' It may be wise to keep special characters out of field names for easier access later on.'
      ),
      HELP_IDS.OBJECT_FIELD_NAME_INVALID
    ]
  }
  return []
}

function validateField(field, visitorContext) {
  const {name, fieldset, ...fieldType} = field
  return 'name' in field
    ? validateFieldName(name)
    : [error('Missing field name', HELP_IDS.OBJECT_FIELD_NAME_INVALID)]
}

function getDuplicateFields(array: Array<Field>): Array<Array<Field>> {
  const dupes: {[string]: Array<Field>} = {}
  array.forEach(field => {
    if (!dupes[field.name]) {
      dupes[field.name] = []
    }
    dupes[field.name].push(field)
  })
  return Object.keys(dupes)
    .map(fieldName => (dupes[fieldName].length > 1 ? dupes[fieldName] : null))
    .filter(Boolean)
}

export default (typeDef, visitorContext) => {
  const problems = []
  const fieldsIsArray = Array.isArray(typeDef.fields)
  if (fieldsIsArray) {
    const fieldsWithNames = typeDef.fields.filter(field => typeof field.name === 'string')

    getDuplicateFields(fieldsWithNames).forEach(dupes => {
      problems.push(
        error(
          `Found ${dupes.length} fields with name "${dupes[0].name}" in object`,
          HELP_IDS.OBJECT_FIELD_NOT_UNIQUE
        )
      )
    })
    if (typeDef.fields.length === 0) {
      problems.push(error('Object should have at least one field', HELP_IDS.OBJECT_FIELDS_INVALID))
    }
  } else {
    problems.push(
      error(
        `The "fields" property must be an array of fields. Instead saw "${typeof typeDef.fields}"`,
        HELP_IDS.OBJECT_FIELDS_INVALID
      )
    )
  }

  return {
    ...typeDef,
    fields: (fieldsIsArray ? typeDef.fields : []).map(field => {
      const {name, ...fieldTypeDef} = field
      const {_problems, ...fieldType} = visitorContext.visit(fieldTypeDef, visitorContext)
      return {
        name,
        ...fieldType,
        _problems: validateField(field, visitorContext).concat(_problems || [])
      }
    }),
    _problems: problems
  }
}
<commit_msg>[schema] Make sure field name regex fail on dash and whitespace (#748)<commit_after>// @flow
import {error, HELP_IDS, warning} from '../createValidationResult'
import inspect from '../../inspect'

const VALID_FIELD_RE = /^[A-Za-z]+[0-9A-Za-z_]*$/
const CONVENTIONAL_FIELD_RE = /^[A-Za-z_]+[0-9A-Za-z_]*$/

function validateFieldName(name): Array<any> {
  if (typeof name !== 'string') {
    return [
      error(
        `Field names must be strings. Saw "${inspect(name)}"`,
        HELP_IDS.OBJECT_FIELD_NAME_INVALID
      )
    ]
  }
  if (name.startsWith('_')) {
    return [
      error(
        `Invalid field name "${name}". Field names cannot start with underscores "_" as it's reserved for system fields.`,
        HELP_IDS.OBJECT_FIELD_NAME_INVALID
      )
    ]
  }

  if (!VALID_FIELD_RE.test(name)) {
    return [
      error(
        `Invalid field name: "${name}". Fields can only contain characters from A-Z, numbers and underscores and should not start with a number (must pass the regular expression ${String(
          VALID_FIELD_RE
        )}).`,
        HELP_IDS.OBJECT_FIELD_NAME_INVALID
      )
    ]
  }
  if (!CONVENTIONAL_FIELD_RE.test(name)) {
    return [
      warning(
        'Thats an interesting field name for sure! But it is... how to put it... a bit... unconventional?' +
          ' It may be wise to keep special characters out of field names for easier access later on.'
      ),
      HELP_IDS.OBJECT_FIELD_NAME_INVALID
    ]
  }
  return []
}

function validateField(field, visitorContext) {
  const {name, fieldset, ...fieldType} = field
  return 'name' in field
    ? validateFieldName(name)
    : [error('Missing field name', HELP_IDS.OBJECT_FIELD_NAME_INVALID)]
}

function getDuplicateFields(array: Array<Field>): Array<Array<Field>> {
  const dupes: {[string]: Array<Field>} = {}
  array.forEach(field => {
    if (!dupes[field.name]) {
      dupes[field.name] = []
    }
    dupes[field.name].push(field)
  })
  return Object.keys(dupes)
    .map(fieldName => (dupes[fieldName].length > 1 ? dupes[fieldName] : null))
    .filter(Boolean)
}

export default (typeDef, visitorContext) => {
  const problems = []
  const fieldsIsArray = Array.isArray(typeDef.fields)
  if (fieldsIsArray) {
    const fieldsWithNames = typeDef.fields.filter(field => typeof field.name === 'string')

    getDuplicateFields(fieldsWithNames).forEach(dupes => {
      problems.push(
        error(
          `Found ${dupes.length} fields with name "${dupes[0].name}" in object`,
          HELP_IDS.OBJECT_FIELD_NOT_UNIQUE
        )
      )
    })
    if (typeDef.fields.length === 0) {
      problems.push(error('Object should have at least one field', HELP_IDS.OBJECT_FIELDS_INVALID))
    }
  } else {
    problems.push(
      error(
        `The "fields" property must be an array of fields. Instead saw "${typeof typeDef.fields}"`,
        HELP_IDS.OBJECT_FIELDS_INVALID
      )
    )
  }

  return {
    ...typeDef,
    fields: (fieldsIsArray ? typeDef.fields : []).map(field => {
      const {name, ...fieldTypeDef} = field
      const {_problems, ...fieldType} = visitorContext.visit(fieldTypeDef, visitorContext)
      return {
        name,
        ...fieldType,
        _problems: validateField(field, visitorContext).concat(_problems || [])
      }
    }),
    _problems: problems
  }
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import './App.css';

import { Container, Grid, Button } from 'semantic-ui-react'
import LoginPanel from './LoginPanel';
import Body from './Body';

import * as auth from './auth';
import ajaxFetch from './ajax';

class App extends Component {
  constructor(props) {
    super(props);

    // initial state
    this.state = {
      user: {
        isLoggedIn: false
      }
    };

    // try and restore the auth from localStorage before the first render
    auth.restoreAuth();

    // event handlers
    this.handleLogin = this.handleLogin.bind(this);
    this.handleLogout = this.handleLogout.bind(this);
  }

  componentDidMount() {
    // modify the state based on non-pure inputs here
    this.setState(this.computeAuthState());
  }

  computeAuthState() {
    return { user: auth.user };
  }

  /* callbacks */
  handleLogin(username, password) {
    // a promise
    return auth.login(username, password).then(() => {
      this.setState(this.computeAuthState());
    });
  }

  handleLogout() {
    auth.logout();

    this.setState(this.computeAuthState());
  }

  doAjax() {
    ajaxFetch('api/somebackendroute');
  }

  render() {
    return (
      <Container className="app">
        <Grid columns={2} divided>
          <Grid.Row>
            <Grid.Column>
              <LoginPanel
                handleLogin={this.handleLogin}
                handleLogout={this.handleLogout}
                user={this.state.user}
              />
            </Grid.Column>

            <Grid.Column>
              <Button onClick={() => this.doAjax()}>Perform Useless 404 Ajax</Button>
            </Grid.Column>
          </Grid.Row>
        </Grid>
        {this.state.user.isLoggedIn ? <Body user={this.state.user} /> : null}
      </Container>
    );
  }
}

export default App;
<commit_msg>Put body into the row<commit_after>import React, { Component } from 'react';
import './App.css';

import { Container, Grid, Button } from 'semantic-ui-react'
import LoginPanel from './LoginPanel';
import Body from './Body';

import * as auth from './auth';
import ajaxFetch from './ajax';

class App extends Component {
  constructor(props) {
    super(props);

    // initial state
    this.state = {
      user: {
        isLoggedIn: false
      }
    };

    // try and restore the auth from localStorage before the first render
    auth.restoreAuth();

    // event handlers
    this.handleLogin = this.handleLogin.bind(this);
    this.handleLogout = this.handleLogout.bind(this);
  }

  componentDidMount() {
    // modify the state based on non-pure inputs here
    this.setState(this.computeAuthState());
  }

  computeAuthState() {
    return { user: auth.user };
  }

  /* callbacks */
  handleLogin(username, password) {
    // a promise
    return auth.login(username, password).then(() => {
      this.setState(this.computeAuthState());
    });
  }

  handleLogout() {
    auth.logout();

    this.setState(this.computeAuthState());
  }

  doAjax() {
    ajaxFetch('api/somebackendroute');
  }

  render() {
    return (
      <Container className="app">
        <Grid columns={2} divided>

          <Grid.Row>
            <Grid.Column>
              <LoginPanel
                handleLogin={this.handleLogin}
                handleLogout={this.handleLogout}
                user={this.state.user}
              />
            </Grid.Column>

            <Grid.Column>
              <Button onClick={() => this.doAjax()}>Perform Useless 404 Ajax</Button>
            </Grid.Column>
          </Grid.Row>

          <Grid.Row>
            <Grid.Column>
              {this.state.user.isLoggedIn ? <Body user={this.state.user} /> : null}
            </Grid.Column>
            <Grid.Column>
              {/* goodies here */}
            </Grid.Column>
          </Grid.Row>

        </Grid>
      </Container>
    );
  }
}

export default App;
<|endoftext|>


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

function HTMLToBBCode (html) {
  return new Parser().parse(html)
}

function nothing () {}

class Parser {
  constructor () {
    this.output = []
    this.lineBuffer = ''
    this.tagBuffer = {}
    this.accumulatingContent = true

    this.tags = {
      a: {
        start: (tag, attrs) => {
          const href = attrs.filter(attr => attr.name === 'href')
          this.addText(`[url=${href[0].value}]`)
        },
        end: () => {
          this.addText('[/url]')
        }
      },
      abbr: this.inline(),
      acronym: this.inline(),
      address: this.block('[i]', '[/i]'),
      article: this.block(),
      aside: this.block(),
      b: this.inline('[b]', '[/b]'),
      big: this.inline('[size=5]', '[/size]'),
      blockquote: this.block('[indent]', '[/indent]'),
      // body: ignore
      br: {
        start: () => this.endLine(),
        end: nothing
      },
      caption: this.inline(), // table related
      center: this.inline('[center]', '[/center]'),
      cite: this.inline('[i]', '[/i]'),
      code: this.block('[code]', '[/code]'),
      col: this.inline(),
      colgroup: this.inline(),
      dd: this.block('[indent]', '[/indent]'),
      del: this.inline('[s]', '[/s]'),
      dfn: this.inline(),
      div: this.block(),
      dl: this.block(),
      dt: this.block('[b][u]', '[/u][/b]'),
      em: this.inline('[i]', '[/i]'),
      figcaption: this.block(),
      figure: this.block(),
      footer: this.block(),
      h1: this.paragraph('[size=7][b]', '[/b][/size]'), // 2em
      h2: this.paragraph('[size=6][b]', '[/b][/size]'), // 1.5em
      h3: this.paragraph('[size=5][b]', '[/b][/size]'), // 1.17em
      h4: this.paragraph('[b]', '[/b]'),
      h5: this.paragraph('[size=3][b]', '[/b][/size]'), // 0.83em
      h6: this.paragraph('[size=2][b]', '[/b][/size]'), // 0.67em
      // head: ignore
      header: this.block(),
      hgroup: this.block(),
      hr: this.block('[hr][/hr]', null, false),
      i: this.inline('[i]', '[/i]'),
      img: {
        start: (tag, attrs) => {
          const src = attrs.filter(attr => attr.name === 'src')
          this.addText(`[img]${src[0].value}[/img]`)
        },
        end: () => {
          this.addText('[/img]')
        }
      },
      ins: this.inline('[u]', '[/u]'),
      kbd: this.inline('[font=Courier New]', '[/font]'),
      li: this.block('[*]', null, false),
      // link: supress
      menu: this.block('[list]', '[/list]'),
      ol: this.block('[list=1]', '[/list]'),
      output: this.inline(),
      p: this.paragraph(),
      pre: this.block('[code]', '[/code]'),
      q: this.inline('“', '”'),
      // ruby: ignore
      // rp: ignore
      // rt: ignore
      s: this.inline('[s]', '[/s]'),
      samp: this.inline('[font=Courier New]', '[/font]'),
      section: this.block(),
      small: this.inline('[size=3]', '[/size]'),
      // source: supress (used w/ video)
      span: this.inline(),
      strike: this.inline('[s]', '[/s]'),
      strong: this.inline('[b]', '[/b]'),
      // style: suppress (BUT DON'T DO THIS FOREVER)
      sub: this.inline('[sub]', '[/sub]'),
      sup: this.inline('[sup]', '[/sup]'),
      table: this.inline('[xtable]', '[/xtable]'),
      // tbody: ignored
      td: this.inline('{td}', '{/td}'),
      // tfoot: ignored
      th: this.inline('{td}[b][center]', '[/center][/b]{/td}'),
      // thead: ignored
      time: this.inline(),
      // title: suppress
      tr: this.inline('{tr}', '{/tr}'),
      u: this.inline('[u]', '[/u]'),
      ul: this.block('[list]', '[/list]'),
      var: this.inline('[i]', '[/i]'),

      $ignore: {
        start: nothing,
        end: nothing
      },
      $suppress: {
        start: () => this.pauseText(),
        end: () => this.resumeText()
      }
    }

    this.tags.body = this.tags.$ignore
    this.tags.head = this.tags.$ignore
    this.tags.hgroup = this.tags.$ignore
    this.tags.html = this.tags.$ignore
    this.tags.link = this.tags.$suppress
    this.tags.ruby = this.tags.$ignore
    this.tags.rp = this.tags.$ignore
    this.tags.rt = this.tags.$ignore
    this.tags.script = this.tags.$suppress
    this.tags.source = this.tags.$suppress
    this.tags.style = this.tags.$suppress
    this.tags.tbody = this.tags.$ignore
    this.tags.tfoot = this.tags.$ignore
    this.tags.thead = this.tags.$ignore
    this.tags.time = this.tags.$ignore
    this.tags.title = this.tags.$suppress
    this.tags.wbr = this.tags.$ignore

    this.styles = {
      'xenforo-spoiler': (tag, name, value) => {
        this.addText(`[spoiler=${value}]`)
        return '[/spoiler]'
      },
      'xenforo-color': (tag, name, value) => {
        this.addText(`[color={$value}]`)
        return '[/color]'
      },
      'xenforo-quote': (tag, name, value) => {
        const bits = value.match(/^(?:(\d+) )?'(.*)'|true/)
        if (bits[2]) {
          this.addText(`[quote="${bits[2]}, post: ${bits[1]}"]`)
        } else if (value !== 'true') {
          this.addText(`[quote="${bits[2]}"]`)
        } else {
          this.addText('[quote]')
        }
        return '[/quote]'
      },
      'text-decoration': (tag, name, valueStr) => {
        const values = valueStr.trim().split(/\s+/).filter(this.textDecorations())
        this.addText(values.map(this.textDecorations(0)).join(''))
        return values.map(this.textDecorations(1)).join('')
      },
      'color': (tag, name, valueStr) => {
        this.addText(`[color=${valueStr}]`)
        return '[/color]'
      },
      'border': () => '',
      'width': () => '',
      'display': () => '',
      'padding': () => {
        this.addText('[indent]')
        return '[/indent]'
      },
      'padding-left': () => {
        this.addText('[indent]')
        return '[/indent]'
      },
      'margin-left': () => {
        this.addText('[indent]')
        return '[/indent]'
      },
      'font-size': (tag, name, value) => {
        const size = value.match(/^(\d*(?:[.]\d+)?)(em|px|pt)?$/)
        if (!size) return ''
        let px = size[1]
        const unit = size[2] || 'px'
        if (unit === 'pt') {
          px *= 1.33333
        } else if (unit === 'em') {
          px *= 13.33333
        }
        let xen = Math.round((px - 5) / 2.8571)
        if (xen > 7) xen = 7
        if (xen === 3) return
        this.addText(`[size=${xen}]`)
        return '[/size]'
      },
      'font-weight': (tag, name, value) => {
        if (value === 'bold' || value === 'bolder' || value >= 700) {
          this.addText(`[b]`)
          return '[/b]'
        } else {
          return ''
        }
      },
      'font-family': (tag, name, value) => {
        return ''
//        this.addText(`[font=${value}]`)
//        return '[/font]'
      },
      'vertical-align': (tag, name, value) => {
        switch (value) {
          case 'super':
            if (tag === 'sup') return ''
            this.addText('[sup]')
            return '[/sup]'
          case 'sub':
            if (tag === 'sub') return ''
            this.addText('[sub]')
            return '[/sub]'
          default:
            return ''
        }
      },
      'text-align': (tag, name, value) => {
        switch (value) {
          case 'center':
            this.addText('[center]')
            return '[/center]'
          case 'right':
            this.addText('[right]')
            return '[/right]'
          case 'left':
            this.addText('[left]')
            return '[/left]'
          default:
            throw new Error('Unknown text alignment: ', value)
        }
      }
    }

    this.textDecorationsMap = {
      'underline': ['[u]', '[/u]'],
      'line-through': ['[s]', '[/s]']
    }

    this.emojiMap = {
      '🙂': ':)',
      '😉': ';)',
      '🙁': ':(',
      '😡': ':mad:',
      '🙃': ':confused:',
      '😎': ':cool:',
      '😛': ':p',
      '😆': ':D',
      '😮': ':o',
      '😳': ':oops:',
      '🙄': ':rolleyes:',
      '😜': 'o_O',
      '😭': ':cry:',
      '😏': ':evil:',
      '😇': ':whistle:',
      '😂': ':lol:',
      '😆😂': ':rofl:',
      '😁': ':grin:',
      '😞': ':sad:',
      '😝': ':sour:'
    }
  }

  pauseText () {
    this.accumulatingContent = false
  }

  resumeText () {
    this.accumulatingContent = true
  }

  addText (text) {
    if (!this.accumulatingContent) return

    const matchEmoji = new RegExp(Object.keys(this.emojiMap).join('|'), 'g')
    this.lineBuffer += text.replace(matchEmoji, match => this.emojiMap[match])
  }

  currentLine () {
    return this.lineBuffer.replace(/\s+/g, ' ').trim()
  }

  endLine () {
    this.output.push(this.currentLine())
    this.lineBuffer = ''
  }

  textDecorations (which) {
    return value => which == null ? this.textDecorationsMap[value] : this.textDecorationsMap[value][which]
  }

  handleStyle (tag, attrs) {
    let foundUnknown = false
    let closeWith = ''
    for (let attr of attrs) {
      if (attr.name === 'style') {
        try {
          const parseCSS = require('css-parse')
          let css = parseCSS(`this { ${attr.value} }`)
          for (let decl of css.stylesheet.rules[0].declarations) {
            let style = this.styles[decl.property]
            if (style) {
              closeWith = style(tag, decl.property, decl.value) + closeWith
              if (/^xenforo-/.test(decl.property)) break
            } else {
              const util = require('util')
              process.emit('debug', `UNKNOWN CSS: ${util.inspect(decl)} ${tag} ${util.inspect(attrs)}`)
            }
          }
        } catch (ex) {
          process.emit('debug', 'INVALID CSS value=' + attr.value + ', ' + ex.stack)
        }
      }
    }
    if (!this.tagBuffer[tag]) this.tagBuffer[tag] = []
    this.tagBuffer[tag].push(closeWith)
  }

  inline (start, end, noStyle) {
    return {
      start: (tag, attrs) => {
        if (!noStyle) this.handleStyle(tag, attrs)
        if (start) this.addText(start)
      },
      end: (tag) => {
        if (end) this.addText(end)
        if (!noStyle) {
          const closeWith = this.tagBuffer[tag].pop()
          if (closeWith) this.addText(closeWith)
        }
      }
    }
  }

  block (start, end, noStyle) {
    return {
      start: (tag, attrs) => {
        if (this.currentLine().length) this.endLine()

        if (!noStyle) this.handleStyle(tag, attrs)
        if (start) this.addText(start)
      },
      end: (tag, attrs) => {
        if (end) this.addText(end)
        if (!noStyle) {
          const closeWith = this.tagBuffer[tag].pop()
          if (closeWith) this.addText(closeWith)
        }
        if (this.currentLine().length) this.endLine()
      }
    }
  }

  paragraph (start, end, noStyle) {
    return {
      start: (tag, attrs) => {
        // paragraphs end the current line, if any
        if (this.currentLine().length) this.endLine()

        // they also inject a blank line between themselves and any previous lines
        if (this.output.length && this.output[this.output.length - 1].length) this.endLine()
        if (!noStyle) this.handleStyle(tag, attrs)
        if (start) this.addText(start)
      },
      end: (tag, attrs) => {
        if (end) this.addText(end)
        if (!noStyle) {
          const closeWith = this.tagBuffer[tag].pop()
          if (closeWith) this.addText(closeWith)
        }
        if (this.currentLine().length) {
          this.endLine()
          this.endLine()
        } else {
          this.endLine()
        }
      }
    }
  }

  async parse (html$) {
    const parse5 = require('parse5')
    const parser = new parse5.SAXParser()
    parser.on('startTag', (tag, attrs, selfClosing, location) => {
      if (this.tags[tag]) {
        this.tags[tag].start(tag, attrs, selfClosing, location)
      } else {
        const util = require('util')
        process.emit('debug', 'UNKNOWN', 'tag:', tag + ', attrs:', util.inspect(attrs) + ', selfClosing:', !!selfClosing + ', location:', location, '\n')
      }
    })
    parser.on('endTag', (tag, attrs, selfClosing, location) => {
      if (this.tags[tag]) {
        this.tags[tag].end(tag, attrs, selfClosing, location)
      } else {
        const util = require('util')
        process.emit('debug', 'UNKNOWN', 'endtag:', tag + ', attrs:', util.inspect(attrs) + ', selfClosing:', !!selfClosing + ', location:', location, '\n')
      }
    })
    parser.on('text', text => this.addText(text))

    parser.end(await html$)
    const fun = require('funstream')
    await fun(parser)
    this.endLine()
    return this.output.join('\n').replace(/\n+$/, '') + '\n'
  }
}
<commit_msg>html-to-bbcode: Improve quote parsing<commit_after>'use strict'
module.exports = HTMLToBBCode

function HTMLToBBCode (html) {
  return new Parser().parse(html)
}

function nothing () {}

class Parser {
  constructor () {
    this.output = []
    this.lineBuffer = ''
    this.tagBuffer = {}
    this.accumulatingContent = true

    this.tags = {
      a: {
        start: (tag, attrs) => {
          const href = attrs.filter(attr => attr.name === 'href')
          this.addText(`[url=${href[0].value}]`)
        },
        end: () => {
          this.addText('[/url]')
        }
      },
      abbr: this.inline(),
      acronym: this.inline(),
      address: this.block('[i]', '[/i]'),
      article: this.block(),
      aside: this.block(),
      b: this.inline('[b]', '[/b]'),
      big: this.inline('[size=5]', '[/size]'),
      blockquote: this.block('[indent]', '[/indent]'),
      // body: ignore
      br: {
        start: () => this.endLine(),
        end: nothing
      },
      caption: this.inline(), // table related
      center: this.inline('[center]', '[/center]'),
      cite: this.inline('[i]', '[/i]'),
      code: this.block('[code]', '[/code]'),
      col: this.inline(),
      colgroup: this.inline(),
      dd: this.block('[indent]', '[/indent]'),
      del: this.inline('[s]', '[/s]'),
      dfn: this.inline(),
      div: this.block(),
      dl: this.block(),
      dt: this.block('[b][u]', '[/u][/b]'),
      em: this.inline('[i]', '[/i]'),
      figcaption: this.block(),
      figure: this.block(),
      footer: this.block(),
      h1: this.paragraph('[size=7][b]', '[/b][/size]'), // 2em
      h2: this.paragraph('[size=6][b]', '[/b][/size]'), // 1.5em
      h3: this.paragraph('[size=5][b]', '[/b][/size]'), // 1.17em
      h4: this.paragraph('[b]', '[/b]'),
      h5: this.paragraph('[size=3][b]', '[/b][/size]'), // 0.83em
      h6: this.paragraph('[size=2][b]', '[/b][/size]'), // 0.67em
      // head: ignore
      header: this.block(),
      hgroup: this.block(),
      hr: this.block('[hr][/hr]', null, false),
      i: this.inline('[i]', '[/i]'),
      img: {
        start: (tag, attrs) => {
          const src = attrs.filter(attr => attr.name === 'src')
          this.addText(`[img]${src[0].value}[/img]`)
        },
        end: () => {
          this.addText('[/img]')
        }
      },
      ins: this.inline('[u]', '[/u]'),
      kbd: this.inline('[font=Courier New]', '[/font]'),
      li: this.block('[*]', null, false),
      // link: supress
      menu: this.block('[list]', '[/list]'),
      ol: this.block('[list=1]', '[/list]'),
      output: this.inline(),
      p: this.paragraph(),
      pre: this.block('[code]', '[/code]'),
      q: this.inline('“', '”'),
      // ruby: ignore
      // rp: ignore
      // rt: ignore
      s: this.inline('[s]', '[/s]'),
      samp: this.inline('[font=Courier New]', '[/font]'),
      section: this.block(),
      small: this.inline('[size=3]', '[/size]'),
      // source: supress (used w/ video)
      span: this.inline(),
      strike: this.inline('[s]', '[/s]'),
      strong: this.inline('[b]', '[/b]'),
      // style: suppress (BUT DON'T DO THIS FOREVER)
      sub: this.inline('[sub]', '[/sub]'),
      sup: this.inline('[sup]', '[/sup]'),
      table: this.inline('[xtable]', '[/xtable]'),
      // tbody: ignored
      td: this.inline('{td}', '{/td}'),
      // tfoot: ignored
      th: this.inline('{td}[b][center]', '[/center][/b]{/td}'),
      // thead: ignored
      time: this.inline(),
      // title: suppress
      tr: this.inline('{tr}', '{/tr}'),
      u: this.inline('[u]', '[/u]'),
      ul: this.block('[list]', '[/list]'),
      var: this.inline('[i]', '[/i]'),

      $ignore: {
        start: nothing,
        end: nothing
      },
      $suppress: {
        start: () => this.pauseText(),
        end: () => this.resumeText()
      }
    }

    this.tags.body = this.tags.$ignore
    this.tags.head = this.tags.$ignore
    this.tags.hgroup = this.tags.$ignore
    this.tags.html = this.tags.$ignore
    this.tags.link = this.tags.$suppress
    this.tags.ruby = this.tags.$ignore
    this.tags.rp = this.tags.$ignore
    this.tags.rt = this.tags.$ignore
    this.tags.script = this.tags.$suppress
    this.tags.source = this.tags.$suppress
    this.tags.style = this.tags.$suppress
    this.tags.tbody = this.tags.$ignore
    this.tags.tfoot = this.tags.$ignore
    this.tags.thead = this.tags.$ignore
    this.tags.time = this.tags.$ignore
    this.tags.title = this.tags.$suppress
    this.tags.wbr = this.tags.$ignore

    this.styles = {
      'xenforo-spoiler': (tag, name, value) => {
        this.addText(`[spoiler=${value}]`)
        return '[/spoiler]'
      },
      'xenforo-color': (tag, name, value) => {
        this.addText(`[color={$value}]`)
        return '[/color]'
      },
      'xenforo-quote': (tag, name, value) => {
        const bits = value.match(/^(?:(\d+) )?(')?(.*)\2|true/)
        if (bits[1]) {
          this.addText(`[quote="${bits[3]}, post: ${bits[1]}"]`)
        } else if (value !== 'true') {
          this.addText(`[quote="${bits[3]}"]`)
        } else {
          this.addText('[quote]')
        }
        return '[/quote]'
      },
      'text-decoration': (tag, name, valueStr) => {
        const values = valueStr.trim().split(/\s+/).filter(this.textDecorations())
        this.addText(values.map(this.textDecorations(0)).join(''))
        return values.map(this.textDecorations(1)).join('')
      },
      'color': (tag, name, valueStr) => {
        this.addText(`[color=${valueStr}]`)
        return '[/color]'
      },
      'border': () => '',
      'width': () => '',
      'display': () => '',
      'padding': () => {
        this.addText('[indent]')
        return '[/indent]'
      },
      'padding-left': () => {
        this.addText('[indent]')
        return '[/indent]'
      },
      'margin-left': () => {
        this.addText('[indent]')
        return '[/indent]'
      },
      'font-size': (tag, name, value) => {
        const size = value.match(/^(\d*(?:[.]\d+)?)(em|px|pt)?$/)
        if (!size) return ''
        let px = size[1]
        const unit = size[2] || 'px'
        if (unit === 'pt') {
          px *= 1.33333
        } else if (unit === 'em') {
          px *= 13.33333
        }
        let xen = Math.round((px - 5) / 2.8571)
        if (xen > 7) xen = 7
        if (xen === 3) return
        this.addText(`[size=${xen}]`)
        return '[/size]'
      },
      'font-weight': (tag, name, value) => {
        if (value === 'bold' || value === 'bolder' || value >= 700) {
          this.addText(`[b]`)
          return '[/b]'
        } else {
          return ''
        }
      },
      'font-family': (tag, name, value) => {
        return ''
//        this.addText(`[font=${value}]`)
//        return '[/font]'
      },
      'vertical-align': (tag, name, value) => {
        switch (value) {
          case 'super':
            if (tag === 'sup') return ''
            this.addText('[sup]')
            return '[/sup]'
          case 'sub':
            if (tag === 'sub') return ''
            this.addText('[sub]')
            return '[/sub]'
          default:
            return ''
        }
      },
      'text-align': (tag, name, value) => {
        switch (value) {
          case 'center':
            this.addText('[center]')
            return '[/center]'
          case 'right':
            this.addText('[right]')
            return '[/right]'
          case 'left':
            this.addText('[left]')
            return '[/left]'
          default:
            throw new Error('Unknown text alignment: ', value)
        }
      }
    }

    this.textDecorationsMap = {
      'underline': ['[u]', '[/u]'],
      'line-through': ['[s]', '[/s]']
    }

    this.emojiMap = {
      '🙂': ':)',
      '😉': ';)',
      '🙁': ':(',
      '😡': ':mad:',
      '🙃': ':confused:',
      '😎': ':cool:',
      '😛': ':p',
      '😆': ':D',
      '😮': ':o',
      '😳': ':oops:',
      '🙄': ':rolleyes:',
      '😜': 'o_O',
      '😭': ':cry:',
      '😏': ':evil:',
      '😇': ':whistle:',
      '😂': ':lol:',
      '😆😂': ':rofl:',
      '😁': ':grin:',
      '😞': ':sad:',
      '😝': ':sour:'
    }
  }

  pauseText () {
    this.accumulatingContent = false
  }

  resumeText () {
    this.accumulatingContent = true
  }

  addText (text) {
    if (!this.accumulatingContent) return

    const matchEmoji = new RegExp(Object.keys(this.emojiMap).join('|'), 'g')
    this.lineBuffer += text.replace(matchEmoji, match => this.emojiMap[match])
  }

  currentLine () {
    return this.lineBuffer.replace(/\s+/g, ' ').trim()
  }

  endLine () {
    this.output.push(this.currentLine())
    this.lineBuffer = ''
  }

  textDecorations (which) {
    return value => which == null ? this.textDecorationsMap[value] : this.textDecorationsMap[value][which]
  }

  handleStyle (tag, attrs) {
    let foundUnknown = false
    let closeWith = ''
    for (let attr of attrs) {
      if (attr.name === 'style') {
        try {
          const parseCSS = require('css-parse')
          let css = parseCSS(`this { ${attr.value} }`)
          for (let decl of css.stylesheet.rules[0].declarations) {
            let style = this.styles[decl.property]
            if (style) {
              closeWith = style(tag, decl.property, decl.value) + closeWith
              if (/^xenforo-/.test(decl.property)) break
            } else {
              const util = require('util')
              process.emit('debug', `UNKNOWN CSS: ${util.inspect(decl)} ${tag} ${util.inspect(attrs)}`)
            }
          }
        } catch (ex) {
          process.emit('debug', 'INVALID CSS value=' + attr.value + ', ' + ex.stack)
        }
      }
    }
    if (!this.tagBuffer[tag]) this.tagBuffer[tag] = []
    this.tagBuffer[tag].push(closeWith)
  }

  inline (start, end, noStyle) {
    return {
      start: (tag, attrs) => {
        if (!noStyle) this.handleStyle(tag, attrs)
        if (start) this.addText(start)
      },
      end: (tag) => {
        if (end) this.addText(end)
        if (!noStyle) {
          const closeWith = this.tagBuffer[tag].pop()
          if (closeWith) this.addText(closeWith)
        }
      }
    }
  }

  block (start, end, noStyle) {
    return {
      start: (tag, attrs) => {
        if (this.currentLine().length) this.endLine()

        if (!noStyle) this.handleStyle(tag, attrs)
        if (start) this.addText(start)
      },
      end: (tag, attrs) => {
        if (end) this.addText(end)
        if (!noStyle) {
          const closeWith = this.tagBuffer[tag].pop()
          if (closeWith) this.addText(closeWith)
        }
        if (this.currentLine().length) this.endLine()
      }
    }
  }

  paragraph (start, end, noStyle) {
    return {
      start: (tag, attrs) => {
        // paragraphs end the current line, if any
        if (this.currentLine().length) this.endLine()

        // they also inject a blank line between themselves and any previous lines
        if (this.output.length && this.output[this.output.length - 1].length) this.endLine()
        if (!noStyle) this.handleStyle(tag, attrs)
        if (start) this.addText(start)
      },
      end: (tag, attrs) => {
        if (end) this.addText(end)
        if (!noStyle) {
          const closeWith = this.tagBuffer[tag].pop()
          if (closeWith) this.addText(closeWith)
        }
        if (this.currentLine().length) {
          this.endLine()
          this.endLine()
        } else {
          this.endLine()
        }
      }
    }
  }

  async parse (html$) {
    const parse5 = require('parse5')
    const parser = new parse5.SAXParser()
    parser.on('startTag', (tag, attrs, selfClosing, location) => {
      if (this.tags[tag]) {
        this.tags[tag].start(tag, attrs, selfClosing, location)
      } else {
        const util = require('util')
        process.emit('debug', 'UNKNOWN', 'tag:', tag + ', attrs:', util.inspect(attrs) + ', selfClosing:', !!selfClosing + ', location:', location, '\n')
      }
    })
    parser.on('endTag', (tag, attrs, selfClosing, location) => {
      if (this.tags[tag]) {
        this.tags[tag].end(tag, attrs, selfClosing, location)
      } else {
        const util = require('util')
        process.emit('debug', 'UNKNOWN', 'endtag:', tag + ', attrs:', util.inspect(attrs) + ', selfClosing:', !!selfClosing + ', location:', location, '\n')
      }
    })
    parser.on('text', text => this.addText(text))

    parser.end(await html$)
    const fun = require('funstream')
    await fun(parser)
    this.endLine()
    return this.output.join('\n').replace(/\n+$/, '') + '\n'
  }
}
<|endoftext|>


<commit_before>import test from 'ava'

import { compose, createStore } from 'redux'
import Immutable from 'immutable'

import { REHYDRATE } from '../src/constants'
import { autoRehydrate } from '../src'

const someString = 'someString'

const createReducer = (actionCallback) => {
  return (state = {arraySpace: ['someInitialValue']}, action) => {
    actionCallback && actionCallback(action)
    return state
  }
}

var finalCreateStore = compose(autoRehydrate())(createStore)

test('rehydrate: with array payload should overwrite substate', (t) => {
  let store = finalCreateStore(createReducer())
  store.dispatch(rehydrate({arraySpace: [1, 2]}))
  let state = store.getState()
  t.deepEqual(state, {arraySpace: [1, 2]})
})

test('rehydrate: rehydrates string state', (t) => {
  let store = finalCreateStore(createReducer())
  store.dispatch(rehydrate({stringSpace: someString}))
  let state = store.getState()
  t.deepEqual(state.stringSpace, someString)
})

const rehydrate = (payload) => ({type: REHYDRATE, payload})

test('can rehydrating immutable state', (t) => {
  let store = finalCreateStore(createReducer())
  let immutableData = Immutable.Map({a: 1})
  store.dispatch(rehydrate({immutableSpace: immutableData}))
  let state = store.getState()
  t.truthy(state.immutableSpace.equals(immutableData))
})
<commit_msg>[tests] fix rehydrate tests, add unknown key test<commit_after>import test from 'ava'

import { compose, createStore } from 'redux'
import Immutable from 'immutable'

import { REHYDRATE } from '../src/constants'
import { autoRehydrate } from '../src'

const someString = 'someString'

const createReducer = (actionCallback) => {
  return (state = {arraySpace: ['someInitialValue'], stringSpace: null, immutableSpace: null}, action) => {
    actionCallback && actionCallback(action)
    return state
  }
}

var finalCreateStore = compose(autoRehydrate())(createStore)

test('rehydrate: with array payload should overwrite substate', (t) => {
  let store = finalCreateStore(createReducer())
  store.dispatch(rehydrate({arraySpace: [1, 2]}))
  let state = store.getState()
  t.deepEqual(state.arraySpace, [1, 2])
})

test('rehydrate: rehydrates string state', (t) => {
  let store = finalCreateStore(createReducer())
  store.dispatch(rehydrate({stringSpace: someString}))
  let state = store.getState()
  t.deepEqual(state.stringSpace, someString)
})

const rehydrate = (payload) => ({type: REHYDRATE, payload})

test('can rehydrating immutable state', (t) => {
  let store = finalCreateStore(createReducer())
  let immutableData = Immutable.Map({a: 1})
  store.dispatch(rehydrate({immutableSpace: immutableData}))
  let state = store.getState()
  t.truthy(state.immutableSpace.equals(immutableData))
})

test('does not rehydrate unknown state keys', (t) => {
  let store = finalCreateStore(createReducer())
  let someData = 1
  store.dispatch(rehydrate({someData}))
  let state = store.getState()
  t.truthy(state.someData === undefined)
})
<|endoftext|>


<commit_before>/*=============================================================================
 * Orange - Custom Event
 * By Hudell - www.hudell.com
 * OrangeCustomEvents.js
 * Version: 1.7.1
 * Free for commercial and non commercial use.
 *=============================================================================*/
 /*:
 * @plugindesc This plugin Will let you add or copy events to the current map
 *
 * @author Hudell
 * @help
 * ============================================================================
 * Latest Version
 * ============================================================================
 *
 * Get the latest version of this script on
 * http://download.hudell.com/OrangeCustomEvents.js
 *
 *=============================================================================*/

var Imported = Imported || {};

if (Imported.MVCommons === undefined) {
  var MVCommons = {};

  (function($){
    $.ajaxLoadFileAsync = function(filePath, mimeType, onLoad, onError){ mimeType = mimeType || "application/json"; var xhr = new XMLHttpRequest(); var name = '$' + filePath.replace(/^.*(\\|\/|\:)/, '').replace(/\..*/, ''); xhr.open('GET', filePath); if (mimeType && xhr.overrideMimeType) { xhr.overrideMimeType(mimeType); } if(onLoad === undefined){ onLoad = function(xhr, filePath, name) { if (xhr.status < 400) { window[name] = JSON.parse(xhr.responseText); DataManager.onLoad(window[name]); } }; } if(onError === undefined) { onError = function() { DataManager._errorUrl = DataManager._errorUrl || filePath; }; } xhr.onload = function() { onLoad.call(this, xhr, filePath, name); }; xhr.onerror = onError; window[name] = null; xhr.send(); };
  })(MVCommons);
}

var OrangeCustomEvents = OrangeCustomEvents || {};

function Game_Custom_Event() {
  this.initialize.apply(this, arguments);
}
Game_Custom_Event.prototype = Object.create(Game_Event.prototype);
Game_Custom_Event.prototype.constructor = Game_Custom_Event;

(function($) {
  "use strict";

  //----------------------------------------------.
  //----------------------------------------------|
  // PROTECTED METHODS                            |
  //----------------------------------------------|
  //----------------------------------------------|

  $.getAnotherMapData = function(mapId, callback) {
    var variableName = '$Map%1'.format(mapId.padZero(3));
    var filename = 'data/Map%1.json'.format(mapId.padZero(3));

    var onLoad = function(xhr, filePath, name) {
      if (xhr.status < 400) {
        window[name] = JSON.parse(xhr.responseText);
        DataManager.onLoad(window[name]);

        callback();
      }
    };

    if (window[variableName] === undefined || window[variableName] === null) {
      MVCommons.ajaxLoadFileAsync(filename, undefined, onLoad);
    } else {
      callback();
    }
  };

  //----------------------------------------------.
  //----------------------------------------------|
  // PUBLIC METHODS                               |
  //----------------------------------------------|
  //----------------------------------------------|

  //----------------------------------------------
  // Game_Custom_Event
  //----------------------------------------------
  Game_Custom_Event.prototype.initialize = function(mapId, eventId, eventData) {
    this._eventData = eventData;
    Game_Event.prototype.initialize.call(this, mapId, eventId);
  };

  Game_Custom_Event.prototype.event = function() {
    return this._eventData;
  };

  Game_Custom_Event.prototype.revive = function(data) {
    return new Game_Custom_Event(data.mapId, data.id, data.eventData);
  };

  //----------------------------------------------
  // Game_System
  //----------------------------------------------
  Game_System.prototype.clearSelfSwitches = function(mapId, eventId) {
    var switches = ["A", "B", "C", "D"];

    switches.forEach(function(switchId) {
      var key = [mapId, eventId, switchId];
      $gameSelfSwitches.setValue(key, false);
    });
  };

  Game_System.prototype.initCustomEvents = function(mapId) {
    if (this._customEvents === undefined) {
      this._customEvents = {};
    }

    if (this._customEvents[mapId] === undefined) {
      this._customEvents[mapId] = {};
    }
  };

  Game_System.prototype.addCustomEvent = function(mapId, event) {
    this.initCustomEvents(mapId);
    this.clearSelfSwitches(mapId, event.id);
    this._customEvents[mapId][event.id] = event;

    return event;
  };

  Game_System.prototype.removeCustomEvent = function(mapId, eventId) {
    this.initCustomEvents(mapId);
    this.clearSelfSwitches(mapId, eventId);
    delete this._customEvents[mapId][eventId];
  };

  Game_System.prototype.clearCustomEvents = function(mapId) {
    this.initCustomEvents();
    this._customEvents[mapId] = {};
  };

  Game_System.prototype.getCustomEvents = function(mapId) {
    this.initCustomEvents();
    return this._customEvents[mapId];
  };

  //----------------------------------------------
  // Game_Map
  //----------------------------------------------
  Game_Map.prototype.getIndexForNewEvent = function() {
    var index = 1;
    while (index < this._events.length && !!this._events[index]) {
      index++;
    }

    return index;
  };

  Game_Map.prototype.addEvent = function(eventData, temporary, index) {
    if (temporary === undefined) {
      temporary = false;
    }

    if (index === undefined) {
      index = this.getIndexForNewEvent();
    }

    eventData.id = index;
    var gameEvent = new Game_Custom_Event(this._mapId, index, eventData);
    $gameSystem.clearSelfSwitches(this._mapId, index);

    this._events[index] = gameEvent;

    if (SceneManager._scene instanceof Scene_Map) {
      var sprite = new Sprite_Character(gameEvent);
      SceneManager._scene._spriteset._characterSprites.push(sprite);
      SceneManager._scene._spriteset._tilemap.addChild(sprite);
    }

    if (temporary === false) {
      $gameSystem.addCustomEvent(this._mapId, eventData);
    }

    return gameEvent;
  };

  var oldGameMap_setupEvents = Game_Map.prototype.setupEvents;
  Game_Map.prototype.setupEvents = function() {
    oldGameMap_setupEvents.call(this);

    var customEvents = $gameSystem.getCustomEvents(this._mapId);
    for (var eventId in customEvents) {
      if (customEvents[eventId] === undefined) continue;
      var newEventId = this.getIndexForNewEvent();

      customEvents[eventId].eventId = newEventId;
      this._events[newEventId] = new Game_Custom_Event(this._mapId, newEventId, customEvents[eventId]);
    }
  };

  Game_Map.prototype.addEventAt = function(eventData, x, y, temporary, index) {
    eventData.x = x;
    eventData.y = y;
    return this.addEvent(eventData, temporary, index);
  };

  Game_Map.prototype.spawnEvent = function(eventData, tileList, temporary) {
    for (var i = 0; i < tileList.length; i++) {
      var newEventData = JsonEx.makeDeepCopy(eventData);
      newEventData.x = tileList[i].x;
      newEventData.y = tileList[i].y;
      this.addEvent(newEventData, temporary);
    }
  };

  Game_Map.prototype.getEventData = function(eventIdOrigin) {
    var event = $dataMap.events[eventIdOrigin];
    if (event === undefined) return undefined;

    return JsonEx.makeDeepCopy(event);
  };

  Game_Map.prototype.getEventDataFrom = function(mapIdOrigin, eventIdOrigin, callback) {
    $.getAnotherMapData(mapIdOrigin, function() {
      var variableName = '$Map%1'.format(mapIdOrigin.padZero(3));

      if (window[variableName] === undefined || window[variableName] === null) return;

      var event = window[variableName].events[eventIdOrigin];
      if (event === undefined) return;

      var eventData = JsonEx.makeDeepCopy(event);
      callback.call(this, eventData);
    });
  };

  Game_Map.prototype.copyEvent = function(eventIdOrigin, x, y, temporary, newIndex) {
    var eventData = this.getEventData(eventIdOrigin);
    if (eventData) {
      $gameMap.addEventAt(eventData, x, y, temporary, newIndex);
    }
  };

  Game_Map.prototype.getRegionTileList = function(regionId) {
    var tileList = [];

    for (var x = 0; x < $gameMap.width(); x++) {
      for (var y = 0; y < $gameMap.height(); y++) {
        if ($gameMap.eventsXy(x, y).length === 0) {
          if ($gameMap.regionId(x, y) == regionId) {
            tileList.push({x : x, y : y});
          }
        }
      }
    }

    return tileList;
  };

  Game_Map.prototype.getRandomRegionTile = function(regionId) {
    var tileList = this.getRegionTileList(regionId);

    if (tileList.length > 0) {
      var index = Math.randomInt(tileList.length);
      return tileList[index];
    }

    return undefined;
  };

  Game_Map.prototype.copyEventToRegion = function(eventIdOrigin, regionId, temporary, newIndex) {
    var tile = this.getRandomRegionTile(regionId);
    if (tile !== undefined) {
      this.copyEvent(eventIdOrigin, tile.x, tile.y, temporary, newIndex);
    }
  };

  Game_Map.prototype.copyEventFrom = function(mapIdOrigin, eventIdOrigin, x, y, temporary, newIndex) {
    this.getEventDataFrom(mapIdOrigin, eventIdOrigin, function(eventData) {
      $gameMap.addEventAt(eventData, x, y, temporary, newIndex);
    });
  };

  Game_Map.prototype.copyEventFromMapToRegion = function(mapIdOrigin, eventIdOrigin, regionId, temporary, newIndex) {
    var tile = this.getRandomRegionTile(regionId);
    if (tile !== undefined) {
      this.copyEventFrom(mapIdOrigin, eventIdOrigin, tile.x, tile.y, temporary, newIndex);
    }
  };

  Game_Map.prototype.spawnMapEvent = function(eventIdOrigin, regionId, temporary) {
    var eventData = this.getEventData(eventIdOrigin);
    var tileList = this.getRegionTileList(regionId);

    if (eventData && tileList) {
      this.spawnEvent(eventData, tileList, temporary);
    }
  };

  Game_Map.prototype.spawnMapEventFrom = function(mapIdOrigin, eventIdOrigin, regionId, temporary) {
    var tileList = this.getRegionTileList(regionId);

    if (tileList.length > 0) {
      this.getEventDataFrom(mapIdOrigin, eventIdOrigin, function(eventData) {
        $gameMap.spawnEvent(eventData, tileList, temporary);
      });
    }
  };

  Game_Interpreter.prototype.getNumericValue = function(stringValue) {
    if (stringValue.substr(0, 1) == '[' && stringValue.substr(-1) == ']') {
      var variableId = parseInt(stringValue.substr(1, stringValue.length - 2), 10);

      if (variableId > 0) {
        return $gameVariables.value(variableId);
      }

      return 0;
    } else {
      return parseInt(stringValue, 10);
    }
  };

  Game_Interpreter.prototype.checkCopyCommands = function(command, args) {
    if (args.length < 2) return;

    if (command.toUpperCase() !== 'COPY' && command.toUpperCase() !== 'SPAWN') return;
    if (args[0].toUpperCase() !== "EVENT") return;

    var eventIdOrigin = this.getNumericValue(args[1]);
    var mapIdOrigin = $gameMap.mapId();
    var isPosition = true;
    var x = 0;
    var y = 0;
    var regionId = 0;
    var temporary = true;
    var hasPosition = false;
    var userIndex;

    if (eventIdOrigin <= 0) return;

    var nextIndex = 2;

    if (args.length >= nextIndex + 3) {
      if (args[nextIndex].toUpperCase() == 'FROM' && args[nextIndex + 1].toUpperCase() == 'MAP') {
        mapIdOrigin = this.getNumericValue(args[nextIndex + 2]);
        nextIndex += 3;
      }
    }

    if (args.length > nextIndex && args[nextIndex].toUpperCase() == 'HERE') {
      isPosition = true;
      hasPosition = true;
      x = this.character(0).x;
      y = this.character(0).y;
      nextIndex++;

    } else if (args.length > nextIndex) {
      if (args[nextIndex].toUpperCase() !== 'TO' && args[nextIndex].toUpperCase() !== 'ON') {
        console.error('OrangeCustomEvents', 'Invalid destination', command, args);
        return;
      }

      nextIndex++;

      if (args.length > nextIndex && args[nextIndex].toUpperCase() == 'REGION') {
        isPosition = false;
        nextIndex++;
      } else if (args.length > nextIndex && args[nextIndex].toUpperCase() == 'POSITION') {
        isPosition = true;
        nextIndex++;
      }
    }
    else {
      console.error('OrangeCustomEvents', 'Incomplete command', command, args);
      return;
    }

    if (isPosition) {
      if (!hasPosition) {
        if (args.length > nextIndex && args[nextIndex].toUpperCase() == 'PLAYER') {
          x = $gamePlayer.x;
          y = $gamePlayer.y;
          nextIndex++;
        } else if (args.length >= nextIndex + 2) {
          x = this.getNumericValue(args[nextIndex]);
          y = this.getNumericValue(args[nextIndex + 1]);

          nextIndex += 2;
        }
        else {
          console.error('OrangeCustomEvents', 'What position?', command, args);
        }
      }
    }
    else {
      if (args.length > nextIndex) {
        regionId = this.getNumericValue(args[nextIndex]);
        nextIndex++;
      }
      else {
        console.error('OrangeCustomEvents', 'What region?', command, args);
      }
    }

    if (args.length > nextIndex) {
      if (args[nextIndex].toUpperCase().startsWith('TEMP')) {
        temporary = true;
        nextIndex++;
      } else if (args[nextIndex].toUpperCase() == 'SAVE') {
        temporary = false;
        nextIndex++;
      }
    }

    if (args.length > nextIndex + 2) {
      if (args[nextIndex].toUpperCase().startsWith('WITH') && args[nextIndex + 1].toUpperCase().startsWith('ID')) {
        userIndex = this.getNumericValue(args[nextIndex + 2]);
      }
    }

    if (isPosition) {
      if (mapIdOrigin == $gameMap.mapId()) {
        $gameMap.copyEvent(eventIdOrigin, x, y, temporary, userIndex);
      } else {
        $gameMap.copyEventFrom(mapIdOrigin, eventIdOrigin, x, y, temporary, userIndex);
      }
    }
    else {
      if (command.toUpperCase() === 'COPY') {
        if (mapIdOrigin == $gameMap.mapId()) {
          $gameMap.copyEventToRegion(eventIdOrigin, regionId, temporary, userIndex);
        } else {
          $gameMap.copyEventFromMapToRegion(mapIdOrigin, eventIdOrigin, regionId, temporary, userIndex);
        }
      } else if (command.toUpperCase() === 'SPAWN') {
        if (mapIdOrigin == $gameMap.mapId()) {
          $gameMap.spawnMapEvent(eventIdOrigin, regionId, temporary);
        } else {
          $gameMap.spawnMapEventFrom(mapIdOrigin, eventIdOrigin, regionId, temporary);
        }
      }
    }
  };

  Game_Interpreter.prototype.checkDeleteCommand = function(command, args) {
    if (args.length != 2) return;

    if (command.toUpperCase() !== 'DELETE') return;
    if (args[0].toUpperCase() !== "THIS") return;
    if (args[1].toUpperCase() !== "EVENT") return;

    $gameSystem.removeCustomEvent(this._mapId, this._eventId);
    this.command214();
  };

  var oldGameInterpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function(command, args) {
    oldGameInterpreter_pluginCommand.call(this, command, args);

    this.checkCopyCommands(command, args);
    this.checkDeleteCommand(command, args);
  };
})(OrangeCustomEvents);

Imported.OrangeCustomEvents = 1.7;<commit_msg>Changed param order<commit_after>/*=============================================================================
 * Orange - Custom Event
 * By Hudell - www.hudell.com
 * OrangeCustomEvents.js
 * Version: 1.7.1
 * Free for commercial and non commercial use.
 *=============================================================================*/
 /*:
 * @plugindesc This plugin Will let you add or copy events to the current map
 *
 * @author Hudell
 * @help
 * ============================================================================
 * Latest Version
 * ============================================================================
 *
 * Get the latest version of this script on
 * http://download.hudell.com/OrangeCustomEvents.js
 *
 *=============================================================================*/

var Imported = Imported || {};

if (Imported.MVCommons === undefined) {
  var MVCommons = {};

  (function($){
    $.ajaxLoadFileAsync = function(filePath, mimeType, onLoad, onError){ mimeType = mimeType || "application/json"; var xhr = new XMLHttpRequest(); var name = '$' + filePath.replace(/^.*(\\|\/|\:)/, '').replace(/\..*/, ''); xhr.open('GET', filePath); if (mimeType && xhr.overrideMimeType) { xhr.overrideMimeType(mimeType); } if(onLoad === undefined){ onLoad = function(xhr, filePath, name) { if (xhr.status < 400) { window[name] = JSON.parse(xhr.responseText); DataManager.onLoad(window[name]); } }; } if(onError === undefined) { onError = function() { DataManager._errorUrl = DataManager._errorUrl || filePath; }; } xhr.onload = function() { onLoad.call(this, xhr, filePath, name); }; xhr.onerror = onError; window[name] = null; xhr.send(); };
  })(MVCommons);
}

var OrangeCustomEvents = OrangeCustomEvents || {};

function Game_Custom_Event() {
  this.initialize.apply(this, arguments);
}
Game_Custom_Event.prototype = Object.create(Game_Event.prototype);
Game_Custom_Event.prototype.constructor = Game_Custom_Event;

(function($) {
  "use strict";

  //----------------------------------------------.
  //----------------------------------------------|
  // PROTECTED METHODS                            |
  //----------------------------------------------|
  //----------------------------------------------|

  $.getAnotherMapData = function(mapId, callback) {
    var variableName = '$Map%1'.format(mapId.padZero(3));
    var filename = 'data/Map%1.json'.format(mapId.padZero(3));

    var onLoad = function(xhr, filePath, name) {
      if (xhr.status < 400) {
        window[name] = JSON.parse(xhr.responseText);
        DataManager.onLoad(window[name]);

        callback();
      }
    };

    if (window[variableName] === undefined || window[variableName] === null) {
      MVCommons.ajaxLoadFileAsync(filename, undefined, onLoad);
    } else {
      callback();
    }
  };

  //----------------------------------------------.
  //----------------------------------------------|
  // PUBLIC METHODS                               |
  //----------------------------------------------|
  //----------------------------------------------|

  //----------------------------------------------
  // Game_Custom_Event
  //----------------------------------------------
  Game_Custom_Event.prototype.initialize = function(mapId, eventId, eventData) {
    this._eventData = eventData;
    Game_Event.prototype.initialize.call(this, mapId, eventId);
  };

  Game_Custom_Event.prototype.event = function() {
    return this._eventData;
  };

  Game_Custom_Event.prototype.revive = function(data) {
    return new Game_Custom_Event(data.mapId, data.id, data.eventData);
  };

  //----------------------------------------------
  // Game_System
  //----------------------------------------------
  Game_System.prototype.clearSelfSwitches = function(mapId, eventId) {
    var switches = ["A", "B", "C", "D"];

    switches.forEach(function(switchId) {
      var key = [mapId, eventId, switchId];
      $gameSelfSwitches.setValue(key, false);
    });
  };

  Game_System.prototype.initCustomEvents = function(mapId) {
    if (this._customEvents === undefined) {
      this._customEvents = {};
    }

    if (this._customEvents[mapId] === undefined) {
      this._customEvents[mapId] = {};
    }
  };

  Game_System.prototype.addCustomEvent = function(mapId, event) {
    this.initCustomEvents(mapId);
    this.clearSelfSwitches(mapId, event.id);
    this._customEvents[mapId][event.id] = event;

    return event;
  };

  Game_System.prototype.removeCustomEvent = function(mapId, eventId) {
    this.initCustomEvents(mapId);
    this.clearSelfSwitches(mapId, eventId);
    delete this._customEvents[mapId][eventId];
  };

  Game_System.prototype.clearCustomEvents = function(mapId) {
    this.initCustomEvents();
    this._customEvents[mapId] = {};
  };

  Game_System.prototype.getCustomEvents = function(mapId) {
    this.initCustomEvents();
    return this._customEvents[mapId];
  };

  //----------------------------------------------
  // Game_Map
  //----------------------------------------------
  Game_Map.prototype.getIndexForNewEvent = function() {
    var index = 1;
    while (index < this._events.length && !!this._events[index]) {
      index++;
    }

    return index;
  };

  Game_Map.prototype.addEvent = function(eventData, temporary, index) {
    if (temporary === undefined) {
      temporary = false;
    }

    if (index === undefined) {
      index = this.getIndexForNewEvent();
    }

    eventData.id = index;
    var gameEvent = new Game_Custom_Event(this._mapId, index, eventData);
    $gameSystem.clearSelfSwitches(this._mapId, index);

    this._events[index] = gameEvent;

    if (SceneManager._scene instanceof Scene_Map) {
      var sprite = new Sprite_Character(gameEvent);
      SceneManager._scene._spriteset._characterSprites.push(sprite);
      SceneManager._scene._spriteset._tilemap.addChild(sprite);
    }

    if (temporary === false) {
      $gameSystem.addCustomEvent(this._mapId, eventData);
    }

    return gameEvent;
  };

  var oldGameMap_setupEvents = Game_Map.prototype.setupEvents;
  Game_Map.prototype.setupEvents = function() {
    oldGameMap_setupEvents.call(this);

    var customEvents = $gameSystem.getCustomEvents(this._mapId);
    for (var eventId in customEvents) {
      if (customEvents[eventId] === undefined) continue;
      var newEventId = this.getIndexForNewEvent();

      customEvents[eventId].eventId = newEventId;
      this._events[newEventId] = new Game_Custom_Event(this._mapId, newEventId, customEvents[eventId]);
    }
  };

  Game_Map.prototype.addEventAt = function(eventData, x, y, temporary, index) {
    eventData.x = x;
    eventData.y = y;
    return this.addEvent(eventData, temporary, index);
  };

  Game_Map.prototype.spawnEvent = function(eventData, tileList, temporary) {
    for (var i = 0; i < tileList.length; i++) {
      var newEventData = JsonEx.makeDeepCopy(eventData);
      newEventData.x = tileList[i].x;
      newEventData.y = tileList[i].y;
      this.addEvent(newEventData, temporary);
    }
  };

  Game_Map.prototype.getEventData = function(eventIdOrigin) {
    var event = $dataMap.events[eventIdOrigin];
    if (event === undefined) return undefined;

    return JsonEx.makeDeepCopy(event);
  };

  Game_Map.prototype.getEventDataFrom = function(mapIdOrigin, eventIdOrigin, callback) {
    $.getAnotherMapData(mapIdOrigin, function() {
      var variableName = '$Map%1'.format(mapIdOrigin.padZero(3));

      if (window[variableName] === undefined || window[variableName] === null) return;

      var event = window[variableName].events[eventIdOrigin];
      if (event === undefined) return;

      var eventData = JsonEx.makeDeepCopy(event);
      callback.call(this, eventData);
    });
  };

  Game_Map.prototype.copyEvent = function(eventIdOrigin, x, y, temporary, newIndex) {
    var eventData = this.getEventData(eventIdOrigin);
    if (eventData) {
      $gameMap.addEventAt(eventData, x, y, temporary, newIndex);
    }
  };

  Game_Map.prototype.getRegionTileList = function(regionId) {
    var tileList = [];

    for (var x = 0; x < $gameMap.width(); x++) {
      for (var y = 0; y < $gameMap.height(); y++) {
        if ($gameMap.eventsXy(x, y).length === 0) {
          if ($gameMap.regionId(x, y) == regionId) {
            tileList.push({x : x, y : y});
          }
        }
      }
    }

    return tileList;
  };

  Game_Map.prototype.getRandomRegionTile = function(regionId) {
    var tileList = this.getRegionTileList(regionId);

    if (tileList.length > 0) {
      var index = Math.randomInt(tileList.length);
      return tileList[index];
    }

    return undefined;
  };

  Game_Map.prototype.copyEventToRegion = function(eventIdOrigin, regionId, temporary, newIndex) {
    var tile = this.getRandomRegionTile(regionId);
    if (tile !== undefined) {
      this.copyEvent(eventIdOrigin, tile.x, tile.y, temporary, newIndex);
    }
  };

  Game_Map.prototype.copyEventFrom = function(mapIdOrigin, eventIdOrigin, x, y, temporary, newIndex) {
    this.getEventDataFrom(mapIdOrigin, eventIdOrigin, function(eventData) {
      $gameMap.addEventAt(eventData, x, y, temporary, newIndex);
    });
  };

  Game_Map.prototype.copyEventFromMapToRegion = function(mapIdOrigin, eventIdOrigin, regionId, temporary, newIndex) {
    var tile = this.getRandomRegionTile(regionId);
    if (tile !== undefined) {
      this.copyEventFrom(mapIdOrigin, eventIdOrigin, tile.x, tile.y, temporary, newIndex);
    }
  };

  Game_Map.prototype.spawnMapEvent = function(eventIdOrigin, regionId, temporary) {
    var eventData = this.getEventData(eventIdOrigin);
    var tileList = this.getRegionTileList(regionId);

    if (eventData && tileList) {
      this.spawnEvent(eventData, tileList, temporary);
    }
  };

  Game_Map.prototype.spawnMapEventFrom = function(mapIdOrigin, eventIdOrigin, regionId, temporary) {
    var tileList = this.getRegionTileList(regionId);

    if (tileList.length > 0) {
      this.getEventDataFrom(mapIdOrigin, eventIdOrigin, function(eventData) {
        $gameMap.spawnEvent(eventData, tileList, temporary);
      });
    }
  };

  Game_Interpreter.prototype.getNumericValue = function(stringValue) {
    if (stringValue.substr(0, 1) == '[' && stringValue.substr(-1) == ']') {
      var variableId = parseInt(stringValue.substr(1, stringValue.length - 2), 10);

      if (variableId > 0) {
        return $gameVariables.value(variableId);
      }

      return 0;
    } else {
      return parseInt(stringValue, 10);
    }
  };

  Game_Interpreter.prototype.checkCopyCommands = function(command, args) {
    if (args.length < 2) return;

    if (command.toUpperCase() !== 'COPY' && command.toUpperCase() !== 'SPAWN') return;
    if (args[0].toUpperCase() !== "EVENT") return;

    var eventIdOrigin = this.getNumericValue(args[1]);
    var mapIdOrigin = $gameMap.mapId();
    var isPosition = true;
    var x = 0;
    var y = 0;
    var regionId = 0;
    var temporary = true;
    var hasPosition = false;
    var userIndex;

    if (eventIdOrigin <= 0) return;

    var nextIndex = 2;

    if (args.length >= nextIndex + 3) {
      if (args[nextIndex].toUpperCase() == 'FROM' && args[nextIndex + 1].toUpperCase() == 'MAP') {
        mapIdOrigin = this.getNumericValue(args[nextIndex + 2]);
        nextIndex += 3;
      }
    }

    if (args.length > nextIndex && args[nextIndex].toUpperCase() == 'HERE') {
      isPosition = true;
      hasPosition = true;
      x = this.character(0).x;
      y = this.character(0).y;
      nextIndex++;

    } else if (args.length > nextIndex) {
      if (args[nextIndex].toUpperCase() !== 'TO' && args[nextIndex].toUpperCase() !== 'ON') {
        console.error('OrangeCustomEvents', 'Invalid destination', command, args);
        return;
      }

      nextIndex++;

      if (args.length > nextIndex && args[nextIndex].toUpperCase() == 'REGION') {
        isPosition = false;
        nextIndex++;
      } else if (args.length > nextIndex && args[nextIndex].toUpperCase() == 'POSITION') {
        isPosition = true;
        nextIndex++;
      }
    }
    else {
      console.error('OrangeCustomEvents', 'Incomplete command', command, args);
      return;
    }

    if (isPosition) {
      if (!hasPosition) {
        if (args.length > nextIndex && args[nextIndex].toUpperCase() == 'PLAYER') {
          x = $gamePlayer.x;
          y = $gamePlayer.y;
          nextIndex++;
        } else if (args.length >= nextIndex + 2) {
          x = this.getNumericValue(args[nextIndex]);
          y = this.getNumericValue(args[nextIndex + 1]);

          nextIndex += 2;
        }
        else {
          console.error('OrangeCustomEvents', 'What position?', command, args);
        }
      }
    }
    else {
      if (args.length > nextIndex) {
        regionId = this.getNumericValue(args[nextIndex]);
        nextIndex++;
      }
      else {
        console.error('OrangeCustomEvents', 'What region?', command, args);
      }
    }

    if (args.length > nextIndex + 2) {
      if (args[nextIndex].toUpperCase().startsWith('WITH') && args[nextIndex + 1].toUpperCase().startsWith('ID')) {
        userIndex = this.getNumericValue(args[nextIndex + 2]);
        nextIndex += 3;
      }
    }

    if (args.length > nextIndex) {
      if (args[nextIndex].toUpperCase().startsWith('TEMP')) {
        temporary = true;
        nextIndex++;
      } else if (args[nextIndex].toUpperCase() == 'SAVE') {
        temporary = false;
        nextIndex++;
      }
    }

    if (isPosition) {
      if (mapIdOrigin == $gameMap.mapId()) {
        $gameMap.copyEvent(eventIdOrigin, x, y, temporary, userIndex);
      } else {
        $gameMap.copyEventFrom(mapIdOrigin, eventIdOrigin, x, y, temporary, userIndex);
      }
    }
    else {
      if (command.toUpperCase() === 'COPY') {
        if (mapIdOrigin == $gameMap.mapId()) {
          $gameMap.copyEventToRegion(eventIdOrigin, regionId, temporary, userIndex);
        } else {
          $gameMap.copyEventFromMapToRegion(mapIdOrigin, eventIdOrigin, regionId, temporary, userIndex);
        }
      } else if (command.toUpperCase() === 'SPAWN') {
        if (mapIdOrigin == $gameMap.mapId()) {
          $gameMap.spawnMapEvent(eventIdOrigin, regionId, temporary);
        } else {
          $gameMap.spawnMapEventFrom(mapIdOrigin, eventIdOrigin, regionId, temporary);
        }
      }
    }
  };

  Game_Interpreter.prototype.checkDeleteCommand = function(command, args) {
    if (args.length != 2) return;

    if (command.toUpperCase() !== 'DELETE') return;
    if (args[0].toUpperCase() !== "THIS") return;
    if (args[1].toUpperCase() !== "EVENT") return;

    $gameSystem.removeCustomEvent(this._mapId, this._eventId);
    this.command214();
  };

  var oldGameInterpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function(command, args) {
    oldGameInterpreter_pluginCommand.call(this, command, args);

    this.checkCopyCommands(command, args);
    this.checkDeleteCommand(command, args);
  };
})(OrangeCustomEvents);

Imported.OrangeCustomEvents = 1.7;<|endoftext|>


<commit_before>const filter = require('gulp-filter');
const path = require('path');
const utils = require('../lib/utils.js');

module.exports = function (gulp, config) {
	'use strict';

	const nitroTmpDirectory = `${config.get('nitro.tmpDirectory')}/views`;
	const processes = [];

	utils.each(config.exporter, (configEntry) => {
		processes.push(
			new Promise((resolve) => {
				// get array of desired view-name language parts
				const langStrings = configEntry.i18n.length
					?  configEntry.i18n.map((lang) => {
							return (lang !== 'default') ? `-${lang}`: '';
						})
					: [''];
				// array of views are configured?
				const hasViewArray = Array.isArray(configEntry.views) && configEntry.views.length > 0;
				const hasAdditionalRoutesArray = Array.isArray(configEntry.additionalRoutes) && configEntry.additionalRoutes.length > 0;
				// views does not have file extensions
				const viewPattern = hasViewArray
					? `{${configEntry.views.join(',')}}`
					: '*';
				// additional views
				const additionalViews =hasAdditionalRoutesArray
					? configEntry.additionalRoutes.map((view) => path.join(nitroTmpDirectory, view))
					: [];

				// merge dumped views with additional views
				const viewFilter = [
					...langStrings.map((lang) => path.join(nitroTmpDirectory, `${viewPattern}${lang}.html`)),
					...additionalViews,
				];

				gulp.src(path.join(nitroTmpDirectory, '**', `*.*`))
					.pipe(filter(viewFilter))
					.pipe(gulp.dest(configEntry.dest))
					.on('end', () => {
						resolve();
					});
			})
		);
	});

	return new Promise((resolve) => {
		Promise.all(processes).then(() => {
			resolve();
		});
	});
};
<commit_msg>fix(exporter): exporting a single view works now<commit_after>const filter = require('gulp-filter');
const path = require('path');
const utils = require('../lib/utils.js');

module.exports = function (gulp, config) {
	'use strict';

	const nitroTmpDirectory = `${config.get('nitro.tmpDirectory')}/views`;
	const processes = [];

	utils.each(config.exporter, (configEntry) => {
		processes.push(
			new Promise((resolve) => {
				// get array of desired view-name language parts
				const langStrings = configEntry.i18n.length
					?  configEntry.i18n.map((lang) => {
							return (lang !== 'default') ? `-${lang}`: '';
						})
					: [''];
				// array of views are configured?
				const hasViewArray = Array.isArray(configEntry.views) && configEntry.views.length > 0;
				const hasAdditionalRoutesArray = Array.isArray(configEntry.additionalRoutes) && configEntry.additionalRoutes.length > 0;
				// views does not have file extensions
				const viewPattern = hasViewArray
					? `{${configEntry.views.join(',')},fantasyNameQWedRayFiZtFlkXd}`
					: '*';
				// additional views
				const additionalViews =hasAdditionalRoutesArray
					? configEntry.additionalRoutes.map((view) => path.join(nitroTmpDirectory, view))
					: [];

				// merge dumped views with additional views
				const viewFilter = [
					...langStrings.map((lang) => path.join(nitroTmpDirectory, `${viewPattern}${lang}.html`)),
					...additionalViews,
				];

				gulp.src(path.join(nitroTmpDirectory, '**', `*.*`))
					.pipe(filter(viewFilter))
					.pipe(gulp.dest(configEntry.dest))
					.on('end', () => {
						resolve();
					});
			})
		);
	});

	return new Promise((resolve) => {
		Promise.all(processes).then(() => {
			resolve();
		});
	});
};
<|endoftext|>