<commit_before>'use strict';
var React = require('react');
var jsonScriptEscape = require('../libs/jsonScriptEscape');
var globals = require('./globals');
var mixins = require('./mixins');
var Navigation = require('./navigation');
var Footer = require('./footer');
var url = require('url');
var Home = require('./home').Home;

var portal = {
    portal_title: 'ENCODE',
    global_sections: [
        {id: 'data', title: 'Data', children: [
            {id: 'assaymatrix', title: 'Matrix', url: '/matrix/?type=Experiment&status=released'},
            {id: 'assaysearch', title: 'Search', url: '/search/?type=Experiment&status=released'},
            {id: 'region-search', title: 'Search by region', url: '/region-search/'},
            {id: 'publications', title: 'Publications', url: '/publications/'}
        ]},
        {id: 'encyclopedia', title: 'Encyclopedia', children: [
            {id: 'aboutannotations', title: 'About', url: '/data/annotations/'},
            {id: 'annotationmatrix', title: 'Matrix', url: '/matrix/?type=Annotation&encyclopedia_version=3&status=released'},
            {id: 'annotationsearch', title: 'Search', url: '/search/?type=Annotation&encyclopedia_version=3&status=released'}
        ]},
        {id: 'materialsmethods', title: 'Materials & Methods', children: [
            {id: 'antibodies', title: 'Antibodies', url: '/search/?type=AntibodyLot&status=released'},
            {id: 'biosamples', title: 'Biosamples', url: '/search/?type=Biosample&status=released'},
            {id: 'references', title: 'Genome References', url: '/data-standards/reference-sequences/'},
            {id: 'sep-mm-1'},
            {id: 'datastandards', title: 'Standards and guidelines', url: '/data-standards/'},
            {id: 'ontologies', title: 'Ontologies', url: '/help/getting-started/#Ontologies'},
            {id: 'fileformats', title: 'File formats', url: '/help/file-formats/'},
            {id: 'softwaretools', title: 'Software tools', url: '/software/'},
            {id: 'pipelines', title: 'Pipelines', url: '/pipelines/'},
            {id: 'datause', title: 'Release policy', url: '/about/data-use-policy/'},
            {id: 'dataaccess', title: 'Data access', url: '/about/data-access/'}
        ]},
        {id: 'help', title: 'Help', children: [
            {id: 'gettingstarted', title: 'Getting started', url: '/help/getting-started/'},
            {id: 'restapi', title: 'REST API', url: '/help/rest-api/'},
            {id: 'projectoverview', title: 'Project overview', url: '/about/contributors/'},
            {id: 'tutorials', title: 'Tutorials', url: '/tutorials/'},
            {id: 'news', title: 'News', url: '/news'},
            {id: 'acknowledgements', title: 'Acknowledgements', url: '/acknowledgements/'},
            {id: 'contact', title: 'Contact', url: '/help/contacts/'}
        ]}
    ]
};

// See https://github.com/facebook/react/issues/2323
var Title = React.createClass({
    render: function() {
        return <title {...this.props}>{this.props.children}</title>;
    },
    componentDidMount: function() {
        var node = document.querySelector('title');
        if (node && !node.getAttribute('data-reactid')) {
            node.setAttribute('data-reactid', this._rootNodeID);
        }
    }
});

// App is the root component, mounted on document.body.
// It lives for the entire duration the page is loaded.
// App maintains state for the
var App = React.createClass({
    mixins: [mixins.Persona, mixins.HistoryAndTriggers],
    triggers: {
        login: 'triggerLogin',
        profile: 'triggerProfile',
        logout: 'triggerLogout'
    },

    getInitialState: function() {
        return {
            errors: [],
            dropdownComponent: undefined
        };
    },

    // Dropdown context using React context mechanism.
    childContextTypes: {
        dropdownComponent: React.PropTypes.string,
        listActionsFor: React.PropTypes.func,
        currentResource: React.PropTypes.func,
        location_href: React.PropTypes.string,
        onDropdownChange: React.PropTypes.func,
        portal: React.PropTypes.object,
        hidePublicAudits: React.PropTypes.bool
    },

    // Retrieve current React context
    getChildContext: function() {
        return {
            dropdownComponent: this.state.dropdownComponent, // ID of component with visible dropdown
            listActionsFor: this.listActionsFor,
            currentResource: this.currentResource,
            location_href: this.props.href,
            onDropdownChange: this.handleDropdownChange, // Function to process dropdown state change
            portal: portal,
            hidePublicAudits: false // True if audits should be hidden on the UI while logged out
        };
    },

    listActionsFor: function(category) {
        if (category === 'context') {
            var context = this.currentResource();
            var name = this.currentAction();
            var context_actions = [];
            Array.prototype.push.apply(context_actions, context.actions || []);
            if (!name && context.default_page) {
                context = context.default_page;
                var actions = context.actions || [];
                for (var i = 0; i < actions.length; i++) {
                    var action = actions[i];
                    if (action.href[0] == '#') {
                        action.href = context['@id'] + action.href;
                    }
                    context_actions.push(action);
                }
            }
            return context_actions;
        }
        if (category === 'user') {
            return this.state.session_properties.user_actions || [];
        }
        if (category === 'global_sections') {
            return portal.global_sections;
        }
    },

    currentResource: function() {
        return this.props.context;
    },

    currentAction: function() {
        var href_url = url.parse(this.props.href);
        var hash = href_url.hash || '';
        var name;
        if (hash.slice(0, 2) === '#!') {
            name = hash.slice(2);
        }
        return name;
    },

    // When current dropdown changes; componentID is _rootNodeID of newly dropped-down component
    handleDropdownChange: function(componentID) {
        // Use React _rootNodeID to uniquely identify a dropdown menu;
        // It's passed in as componentID
        this.setState({dropdownComponent: componentID});
    },

    handleAutocompleteChosenChange: function(chosen) {
        this.setState({autocompleteTermChosen: chosen});
    },

    handleAutocompleteFocusChange: function(focused) {
        this.setState({autocompleteFocused: focused});
    },

    handleAutocompleteHiddenChange: function(hidden) {
        this.setState({autocompleteHidden: hidden});
    },

    // Handle a click outside a dropdown menu by clearing currently dropped down menu
    handleLayoutClick: function(e) {
        if (this.state.dropdownComponent !== undefined) {
            this.setState({dropdownComponent: undefined});
        }
    },

    // If ESC pressed while drop-down menu open, close the menu
    handleKey: function(e) {
        if (e.which === 27) {
            if (this.state.dropdownComponent !== undefined) {
                e.preventDefault();
                this.handleDropdownChange(undefined);
            } else if (!this.state.autocompleteHidden) {
                e.preventDefault();
                this.handleAutocompleteHiddenChange(true);
            }
        } else if (e.which === 13 && this.state.autocompleteFocused && !this.state.autocompleteTermChosen) {
            e.preventDefault();
        }
    },

    // Once the app component is mounted, bind keydowns to handleKey function
    componentDidMount: function() {
        globals.bindEvent(window, 'keydown', this.handleKey);
    },

    render: function() {
        console.log('render app');
        var content, containerClass;
        var context = this.props.context;
        var href_url = url.parse(this.props.href);
        // Switching between collections may leave component in place
        var key = context && context['@id'] && context['@id'].split('?')[0];
        var current_action = this.currentAction();
        if (!current_action && context.default_page) {
            context = context.default_page;
            content = <Home context={context} />;
            containerClass = 'container-homepage';
        } else if (context) {
            var ContentView = globals.content_views.lookup(context, current_action);
            content = <ContentView context={context} />;
            containerClass = 'container';
        }
        var errors = this.state.errors.map(function (error) {
            return

;
        });

        var appClass = 'done';
        if (this.props.slow) {
            appClass = 'communicating';
        }

        var title = context.title || context.name || context.accession || context['@id'];
        if (title && title != 'Home') {
            title = title + ' – ' + portal.portal_title;
        } else {
            title = portal.portal_title;
        }

        var canonical = this.props.href;
        if (context.canonical_uri) {
            if (href_url.host) {
                canonical = (href_url.protocol || '') + '//' + href_url.host + context.canonical_uri;
            } else {
                canonical = context.canonical_uri;
            }
        }

        // Google does not update the content of 301 redirected pages
        var base;
        if (({'http://www.encodeproject.org/': 1, 'http://encodeproject.org/': 1})[canonical]) {
            base = canonical = 'https://www.encodeproject.org/';
            this.historyEnabled = false;
        }

        return (

                    <meta charSet="utf-8" />
                    <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
                    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
                    <Title>{title}</Title>
                    {base ? <base href={base}/> : null}
                    <link rel="canonical" href={canonical} />

                    <link rel="stylesheet" href={this.props.styles} />

                                <Navigation />

                                    {content}

                                {errors}

        );
    },

    statics: {
        getRenderedProps: function (document) {
            var props = {};
            // Ensure the initial render is exactly the same
            props.href = document.querySelector('link[rel="canonical"]').getAttribute('href');
            props.styles = document.querySelector('link[rel="stylesheet"]').getAttribute('href');
            var script_props = document.querySelectorAll('script[data-prop-name]');
            for (var i = 0; i < script_props.length; i++) {
                var elem = script_props[i];
                var value = elem.text;
                var elem_type = elem.getAttribute('type') || '';
                if (elem_type == 'application/json' || elem_type.slice(-5) == '+json') {
                    value = JSON.parse(value);
                }
                props[elem.getAttribute('data-prop-name')] = value;
            }
            return props;
        }
    }
});

module.exports = App;
<commit_msg>Add color mappings to app React context object<commit_after>'use strict';
var React = require('react');
var jsonScriptEscape = require('../libs/jsonScriptEscape');
var globals = require('./globals');
var mixins = require('./mixins');
var Navigation = require('./navigation');
var Footer = require('./footer');
var url = require('url');
var Home = require('./home').Home;
var DataColors = require('./datacolors');

var portal = {
    portal_title: 'ENCODE',
    global_sections: [
        {id: 'data', title: 'Data', children: [
            {id: 'assaymatrix', title: 'Matrix', url: '/matrix/?type=Experiment&status=released'},
            {id: 'assaysearch', title: 'Search', url: '/search/?type=Experiment&status=released'},
            {id: 'region-search', title: 'Search by region', url: '/region-search/'},
            {id: 'publications', title: 'Publications', url: '/publications/'}
        ]},
        {id: 'encyclopedia', title: 'Encyclopedia', children: [
            {id: 'aboutannotations', title: 'About', url: '/data/annotations/'},
            {id: 'annotationmatrix', title: 'Matrix', url: '/matrix/?type=Annotation&encyclopedia_version=3&status=released'},
            {id: 'annotationsearch', title: 'Search', url: '/search/?type=Annotation&encyclopedia_version=3&status=released'}
        ]},
        {id: 'materialsmethods', title: 'Materials & Methods', children: [
            {id: 'antibodies', title: 'Antibodies', url: '/search/?type=AntibodyLot&status=released'},
            {id: 'biosamples', title: 'Biosamples', url: '/search/?type=Biosample&status=released'},
            {id: 'references', title: 'Genome References', url: '/data-standards/reference-sequences/'},
            {id: 'sep-mm-1'},
            {id: 'datastandards', title: 'Standards and guidelines', url: '/data-standards/'},
            {id: 'ontologies', title: 'Ontologies', url: '/help/getting-started/#Ontologies'},
            {id: 'fileformats', title: 'File formats', url: '/help/file-formats/'},
            {id: 'softwaretools', title: 'Software tools', url: '/software/'},
            {id: 'pipelines', title: 'Pipelines', url: '/pipelines/'},
            {id: 'datause', title: 'Release policy', url: '/about/data-use-policy/'},
            {id: 'dataaccess', title: 'Data access', url: '/about/data-access/'}
        ]},
        {id: 'help', title: 'Help', children: [
            {id: 'gettingstarted', title: 'Getting started', url: '/help/getting-started/'},
            {id: 'restapi', title: 'REST API', url: '/help/rest-api/'},
            {id: 'projectoverview', title: 'Project overview', url: '/about/contributors/'},
            {id: 'tutorials', title: 'Tutorials', url: '/tutorials/'},
            {id: 'news', title: 'News', url: '/news'},
            {id: 'acknowledgements', title: 'Acknowledgements', url: '/acknowledgements/'},
            {id: 'contact', title: 'Contact', url: '/help/contacts/'}
        ]}
    ]
};

// Keep lists of currently known project and biosample_type. As new project and biosample_type
// enter the system, these lists must be updated.
const projectList = [
    'ENCODE',
    'Roadmap',
    'modENCODE',
    'modERN',
    'GGR'
];
const biosampleTypeList = [
    'immortalized cell line',
    'tissue',
    'primary cell',
    'whole organisms',
    'stem cell',
    'in vitro differentiated cells',
    'induced pluripotent stem cell line',
    'secondary cell'
];

// See https://github.com/facebook/react/issues/2323
var Title = React.createClass({
    render: function() {
        return <title {...this.props}>{this.props.children}</title>;
    },
    componentDidMount: function() {
        var node = document.querySelector('title');
        if (node && !node.getAttribute('data-reactid')) {
            node.setAttribute('data-reactid', this._rootNodeID);
        }
    }
});

// App is the root component, mounted on document.body.
// It lives for the entire duration the page is loaded.
// App maintains state for the
var App = React.createClass({
    mixins: [mixins.Persona, mixins.HistoryAndTriggers],
    triggers: {
        login: 'triggerLogin',
        profile: 'triggerProfile',
        logout: 'triggerLogout'
    },

    getInitialState: function() {
        return {
            errors: [],
            dropdownComponent: undefined
        };
    },

    // Dropdown context using React context mechanism.
    childContextTypes: {
        dropdownComponent: React.PropTypes.string,
        listActionsFor: React.PropTypes.func,
        currentResource: React.PropTypes.func,
        location_href: React.PropTypes.string,
        onDropdownChange: React.PropTypes.func,
        portal: React.PropTypes.object,
        hidePublicAudits: React.PropTypes.bool,
        projectColors: React.PropTypes.object,
        biosampleTypeColors: React.PropTypes.object
    },

    // Retrieve current React context
    getChildContext: function() {
        // Make `project` and `biosample_type` color mappings for downstream modules to use.
        let projectColors = new DataColors(projectList);
        let biosampleTypeColors = new DataColors(biosampleTypeList);

        return {
            dropdownComponent: this.state.dropdownComponent, // ID of component with visible dropdown
            listActionsFor: this.listActionsFor,
            currentResource: this.currentResource,
            location_href: this.props.href,
            onDropdownChange: this.handleDropdownChange, // Function to process dropdown state change
            portal: portal,
            hidePublicAudits: false, // True if audits should be hidden on the UI while logged out
            projectColors: projectColors,
            biosampleTypeColors: biosampleTypeColors
        };
    },

    listActionsFor: function(category) {
        if (category === 'context') {
            var context = this.currentResource();
            var name = this.currentAction();
            var context_actions = [];
            Array.prototype.push.apply(context_actions, context.actions || []);
            if (!name && context.default_page) {
                context = context.default_page;
                var actions = context.actions || [];
                for (var i = 0; i < actions.length; i++) {
                    var action = actions[i];
                    if (action.href[0] == '#') {
                        action.href = context['@id'] + action.href;
                    }
                    context_actions.push(action);
                }
            }
            return context_actions;
        }
        if (category === 'user') {
            return this.state.session_properties.user_actions || [];
        }
        if (category === 'global_sections') {
            return portal.global_sections;
        }
    },

    currentResource: function() {
        return this.props.context;
    },

    currentAction: function() {
        var href_url = url.parse(this.props.href);
        var hash = href_url.hash || '';
        var name;
        if (hash.slice(0, 2) === '#!') {
            name = hash.slice(2);
        }
        return name;
    },

    // When current dropdown changes; componentID is _rootNodeID of newly dropped-down component
    handleDropdownChange: function(componentID) {
        // Use React _rootNodeID to uniquely identify a dropdown menu;
        // It's passed in as componentID
        this.setState({dropdownComponent: componentID});
    },

    handleAutocompleteChosenChange: function(chosen) {
        this.setState({autocompleteTermChosen: chosen});
    },

    handleAutocompleteFocusChange: function(focused) {
        this.setState({autocompleteFocused: focused});
    },

    handleAutocompleteHiddenChange: function(hidden) {
        this.setState({autocompleteHidden: hidden});
    },

    // Handle a click outside a dropdown menu by clearing currently dropped down menu
    handleLayoutClick: function(e) {
        if (this.state.dropdownComponent !== undefined) {
            this.setState({dropdownComponent: undefined});
        }
    },

    // If ESC pressed while drop-down menu open, close the menu
    handleKey: function(e) {
        if (e.which === 27) {
            if (this.state.dropdownComponent !== undefined) {
                e.preventDefault();
                this.handleDropdownChange(undefined);
            } else if (!this.state.autocompleteHidden) {
                e.preventDefault();
                this.handleAutocompleteHiddenChange(true);
            }
        } else if (e.which === 13 && this.state.autocompleteFocused && !this.state.autocompleteTermChosen) {
            e.preventDefault();
        }
    },

    // Once the app component is mounted, bind keydowns to handleKey function
    componentDidMount: function() {
        globals.bindEvent(window, 'keydown', this.handleKey);
    },

    render: function() {
        console.log('render app');
        var content, containerClass;
        var context = this.props.context;
        var href_url = url.parse(this.props.href);
        // Switching between collections may leave component in place
        var key = context && context['@id'] && context['@id'].split('?')[0];
        var current_action = this.currentAction();
        if (!current_action && context.default_page) {
            context = context.default_page;
            content = <Home context={context} />;
            containerClass = 'container-homepage';
        } else if (context) {
            var ContentView = globals.content_views.lookup(context, current_action);
            content = <ContentView context={context} />;
            containerClass = 'container';
        }
        var errors = this.state.errors.map(function (error) {
            return

;
        });

        var appClass = 'done';
        if (this.props.slow) {
            appClass = 'communicating';
        }

        var title = context.title || context.name || context.accession || context['@id'];
        if (title && title != 'Home') {
            title = title + ' – ' + portal.portal_title;
        } else {
            title = portal.portal_title;
        }

        var canonical = this.props.href;
        if (context.canonical_uri) {
            if (href_url.host) {
                canonical = (href_url.protocol || '') + '//' + href_url.host + context.canonical_uri;
            } else {
                canonical = context.canonical_uri;
            }
        }

        // Google does not update the content of 301 redirected pages
        var base;
        if (({'http://www.encodeproject.org/': 1, 'http://encodeproject.org/': 1})[canonical]) {
            base = canonical = 'https://www.encodeproject.org/';
            this.historyEnabled = false;
        }

        return (

                    <meta charSet="utf-8" />
                    <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
                    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
                    <Title>{title}</Title>
                    {base ? <base href={base}/> : null}
                    <link rel="canonical" href={canonical} />

                    <link rel="stylesheet" href={this.props.styles} />

                                <Navigation />

                                    {content}

                                {errors}

        );
    },

    statics: {
        getRenderedProps: function (document) {
            var props = {};
            // Ensure the initial render is exactly the same
            props.href = document.querySelector('link[rel="canonical"]').getAttribute('href');
            props.styles = document.querySelector('link[rel="stylesheet"]').getAttribute('href');
            var script_props = document.querySelectorAll('script[data-prop-name]');
            for (var i = 0; i < script_props.length; i++) {
                var elem = script_props[i];
                var value = elem.text;
                var elem_type = elem.getAttribute('type') || '';
                if (elem_type == 'application/json' || elem_type.slice(-5) == '+json') {
                    value = JSON.parse(value);
                }
                props[elem.getAttribute('data-prop-name')] = value;
            }
            return props;
        }
    }
});

module.exports = App;
<|endoftext|>


<commit_before>
import { expect } from 'chai';

import ChunkManager, {LOAD, printTileConnections}
    from '../../../client/src/chunk-manager';

const RG = require('../../../client/src/battles');
RG.World = require('../../../client/src/world');

const RGTest = require('../../roguetest');

describe('ChunkManager', () => {

    it('stores the state of world area/chunks ', () => {
        const game = new RG.Game.Main();
        const area = new RG.World.Area('north', 4, 4, 100, 100);
        const world = new RG.World.Top('World');
        const player = new RG.Actor.Rogue('player');
        player.setIsPlayer(true);
        world.addArea(area);
        game.addPlace(world);
        // game.addPlayer(player);

        expect(game.getLevels().length).to.equal(16);
        const manager = new ChunkManager(game, area);

        const tiles = area.getTiles();
        let level0 = tiles[0][0].getLevel();
        const conns = level0.getConnections();
        const nConns = conns.length;
        expect(nConns).to.be.above(50);
        RGTest.verifyConnectivity(conns, 'Tile level 0,0 OK');

        manager.serializeArea();
        expect(game.getLevels().length).to.equal(0);
        expect(manager.getLoadState(0, 0)).to.equal(LOAD.JSON);

        manager.setPlayerTile(0, 0);
        expect(manager.getLoadState(0, 0)).to.equal(LOAD.LOADED);
        expect(manager.getLoadState(0, 1)).to.equal(LOAD.LOADED);
        expect(manager.getLoadState(1, 0)).to.equal(LOAD.LOADED);
        expect(manager.getLoadState(1, 1)).to.equal(LOAD.LOADED);

        level0 = manager.area.getTiles()[1][0].getLevel();
        // const tile10 = manager.area.getTiles()[1][0];

        const conns0 = level0.getConnections();
        RGTest.verifyConnectivity(conns0, 'Tile level 0,0 OK');

        level0 = manager.area.getTiles()[0][0].getLevel();
        const newConns = level0.getConnections();
        const newNConns = newConns.length;
        RGTest.verifyConnectivity(newConns, 'Tile level 0,0 OK');
        expect(game.getLevels().length).to.equal(4);
        expect(newNConns).to.equal(nConns);

        manager.setPlayerTile(1, 0, 0, 0);
        expect(manager.getLoadState(2, 0)).to.equal(LOAD.LOADED);
        expect(manager.getLoadState(2, 1)).to.equal(LOAD.LOADED);
        expect(game.getLevels().length).to.equal(6);

        manager.setPlayerTile(2, 0, 1, 0);
        expect(manager.getLoadState(0, 0)).to.equal(LOAD.JSON);
        expect(manager.getLoadState(0, 1)).to.equal(LOAD.JSON);
        expect(manager.getLoadState(3, 0)).to.equal(LOAD.LOADED);
        expect(manager.getLoadState(3, 1)).to.equal(LOAD.LOADED);
        expect(game.getLevels().length).to.equal(6);

        manager.setPlayerTile(2, 1, 2, 0);
        expect(game.getLevels().length).to.equal(9);
    });
});
<commit_msg>Added two unit tests, one for tile loading/reloading when player moves. 2nd checks functionality after game restore.<commit_after>
import { expect } from 'chai';

import ChunkManager, {LOAD} from '../../../client/src/chunk-manager';

const RG = require('../../../client/src/battles');
RG.World = require('../../../client/src/world');

const RGTest = require('../../roguetest');

describe('ChunkManager', () => {

    let game = null;
    let area = null;
    let world = null;
    let player = null;

    beforeEach(() => {
        game = new RG.Game.Main();
        area = new RG.World.Area('north', 4, 4, 100, 100);
        world = new RG.World.Top('World');
        player = new RG.Actor.Rogue('player');
        player.setIsPlayer(true);
        world.addArea(area);
        game.addPlace(world);
    });

    it('stores the state of world area/chunks ', () => {
        // game.addPlayer(player);

        const manager = new ChunkManager(game, area);
        expect(game.getLevels().length).to.equal(16);

        const tiles = area.getTiles();
        let level0 = tiles[0][0].getLevel();
        const conns = level0.getConnections();
        const nConns = conns.length;
        expect(nConns).to.be.above(50);
        RGTest.verifyConnectivity(conns, 'Tile level 0,0 OK');

        manager.serializeArea();
        expect(game.getLevels().length).to.equal(0);
        expect(manager.getLoadState(0, 0)).to.equal(LOAD.JSON);

        manager.setPlayerTile(0, 0);
        expect(manager.getLoadState(0, 0)).to.equal(LOAD.LOADED);
        expect(manager.getLoadState(0, 1)).to.equal(LOAD.LOADED);
        expect(manager.getLoadState(1, 0)).to.equal(LOAD.LOADED);
        expect(manager.getLoadState(1, 1)).to.equal(LOAD.LOADED);

        level0 = manager.area.getTiles()[1][0].getLevel();
        // const tile10 = manager.area.getTiles()[1][0];

        const conns0 = level0.getConnections();
        RGTest.verifyConnectivity(conns0, 'Tile level 0,0 OK');

        level0 = manager.area.getTiles()[0][0].getLevel();
        const newConns = level0.getConnections();
        const newNConns = newConns.length;
        RGTest.verifyConnectivity(newConns, 'Tile level 0,0 OK');
        expect(game.getLevels().length).to.equal(4);
        expect(newNConns).to.equal(nConns);

        manager.setPlayerTile(1, 0, 0, 0);
        expect(manager.getLoadState(2, 0)).to.equal(LOAD.LOADED);
        expect(manager.getLoadState(2, 1)).to.equal(LOAD.LOADED);
        expect(game.getLevels().length).to.equal(6);

        manager.setPlayerTile(2, 0, 1, 0);
        expect(manager.getLoadState(0, 0)).to.equal(LOAD.JSON);
        expect(manager.getLoadState(0, 1)).to.equal(LOAD.JSON);
        expect(manager.getLoadState(3, 0)).to.equal(LOAD.LOADED);
        expect(manager.getLoadState(3, 1)).to.equal(LOAD.LOADED);
        expect(game.getLevels().length).to.equal(6);

        manager.setPlayerTile(2, 1, 2, 0);
        expect(game.getLevels().length).to.equal(9);
    });

    it('loads/restores chunks when player moves', () => {
        game.addPlayer(player);
        const manager = game.getChunkManager();
        expect(manager).to.exist;

        const playerLevel = player.getLevel();
        RG.POOL.emitEvent(RG.EVT_TILE_CHANGED, {actor: player,
            target: playerLevel});

        const playerPos = game.getPlayerOwPos();
        expect(playerPos).to.deep.equal([]);

        game.movePlayer(3, 3);
        expect(manager.getLoadState(3, 3)).to.equal(LOAD.LOADED);
        expect(manager.getLoadState(3, 2)).to.equal(LOAD.LOADED);
        expect(manager.getLoadState(2, 3)).to.equal(LOAD.LOADED);
        expect(manager.getLoadState(2, 2)).to.equal(LOAD.LOADED);

        const numLoaded = manager.getNumInState(LOAD.LOADED);
        const numJSON = manager.getNumInState(LOAD.JSON);
        expect(numLoaded).to.equal(4);
        expect(numJSON).to.equal(4 * 4 - numLoaded);

        const levels = area.getLevels();
        levels.forEach(level => {
            const msg = `Level ${level.getID()} has parent`;
            expect(level.getParent(), msg).to.exist;
        });
    });

    it('prevents loading of the full world after restore', () => {
        game.addPlayer(player);
        const manager = game.getChunkManager();
        expect(manager).to.exist;

        game.movePlayer(2, 2);
        const numLoaded = manager.getNumInState(LOAD.LOADED);
        expect(numLoaded).to.equal(9);

        world.getConf().createAllZones = false;

        const json = game.toJSON();

        const fromJSON = new RG.Game.FromJSON();
        const newGame = fromJSON.createGame(json);
        expect(newGame).to.exist;

        const newManager = newGame.getChunkManager();
        const newNumLoaded = newManager.getNumInState(LOAD.LOADED);
        expect(newNumLoaded).to.equal(9);

    });

});
<|endoftext|>


<commit_before>/*
 === octapushJS.pluginName ===
 Author  : Fadhly Permata
 eMail   : fadhly.permata@gmail.com
 URL     : www.octapush.com

 === Credits ===
 Prime Developer : Fadhly Permata

 === Contributors ===
 ... just type your name here after editing the script ...

 === THANKS TO : ===
 - CORS Handling : Monsur Hossain (https://www.html5rocks.com/en/tutorials/cors/)
 - https://www.w3.org/
 - MDN : https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
 */

/**
 * NOTE:
 * - CORS test URL: http://html5rocks-cors.s3-website-us-east-1.amazonaws.com/index.html
 * - RESTFULL test URL: https://reqres.in/api/users
 */

(function (w) {
    'use strict';
    if (!w.octapushJS || !w._o_) {
        alert('octapushJS.ajax has dependency with "octapush.js". Please add the file first.');
        return;

    } else {
        const version = '1.7.02.21';

        var internal = {
            parseAndCallAjax: function (method, params) {
                var data = null;
                var success = null;

                if (!_o_.compare.isNullOrEmpty(params[1]) && !_o_.compare.isFunction(params[1]))
                    data = params[1];

                if (!_o_.compare.isNullOrEmpty(params[1]) && _o_.compare.isFunction(params[1]))
                    success = params[1];
                else {
                    success = params[2];
                }

                params = {
                    url: params[0],
                    data: data || null,
                    method: method,
                    success: success || null
                };

                _o_.ajax.request(params);
            }
        };

        _o_.ajax = Object.assign(_o_.utility.ifNull(_o_.ajax, {}), {
            request: function (params) {
                if (_o_.compare.isNullOrEmpty(params) || _o_.compare.isNullOrEmpty(params.url)) return;

                params = {
                    url: params.url || null,
                    data: params.data || null,
                    method: _o_.utility.ifNull(params.method, 'GET'),
                    success: params.success || null,
                    error: params.error || null,
                    headers: params.headers || {},
                    withCredentials: params.withCredentials || false
                };

                var xhr = null;

                // BOF: CROSS BROWSER SUPPORT
                // Chrome/Firefox/Opera/Safari/IE10+
                if (_o_.compare.isDefined(_o_.utility.getType(XMLHttpRequest))) {
                    xhr = new XMLHttpRequest();

                } else {
                    // check for XDomainRequest object
                    if (_o_.compare.isDefined(_o_.getType(XDomainRequest))) {
                        xhr = new XDomainRequest();

                    } else {
                        version = [
                            "MSXML2.XmlHttp.6.0",
                            "MSXML2.XmlHttp.5.0",
                            "MSXML2.XmlHttp.4.0",
                            "MSXML2.XmlHttp.3.0",
                            "MSXML2.XmlHttp.2.0",
                            "Microsoft.XmlHttp"
                        ];

                        // create xhr using higher version
                        for (var i = 0; i < version.length; i++) {
                            try {

                            } catch (e) {
                                if (!_o_.compare.isNullOrEmpty(params.error) && _o_.compare.isFunction(params.error))
                                    params.error(e);
                            }
                        }
                    }
                }
                // EOF: CROSS BROWSER SUPPORT

                if (params.method.toLowerCase() === 'get')
                    params.url = params.url + (_o_.compare.isNullOrEmpty(params.data) ? '' : '?' + params.data);

                xhr.open(params.method, params.url, true);

                // use credentials
                xhr.withCredentials = params.withCredentials;

                // set headers (preflight mode)
                _o_.utility.each(params.headers, function (key, val) {
                    if (val)
                        xhr.setRequestHeader(key, val);
                });

                // set response type & override mime type
                if (!_o_.compare.isNullOrEmpty(params.dataType)) {
                    xhr.responseType = params.dataType;

                    // var lType = ['', 'arraybuffer', 'blob', 'document', 'json', 'text']
                    // var lMime = ['application/json'];
                    //xhr.overrideMimeType('application/json');
                }

                xhr.send(params.method.toLowerCase() === 'get' ? null : params.data);

                xhr.onreadystatechange = function () {
                    if (xhr.readyState === XMLHttpRequest.DONE) {
                        if (xhr.status === 200 || xhr.status === 201 || xhr.status === 200) {
                            if (!_o_.compare.isNullOrEmpty(params.success) && _o_.compare.isFunction(params.success))
                                params.success(xhr);

                        } else {
                            if (!_o_.compare.isNullOrEmpty(params.error) && _o_.compare.isFunction(params.error))
                                params.error(xhr);
                        }
                    }
                };
            },

            // function (url, data, success)
            get: function (params) {
                if (arguments.length == 1 && _o_.compare.isJsonObject(params))
                    _o_.ajax.request(params);

                else
                    internal.parseAndCallAjax('GET', arguments);
            },

            // function (url, data, success)
            post: function (params) {
                if (arguments.length == 1 && _o_.compare.isJsonObject(params))
                    _o_.ajax.request(params);

                else
                    internal.parseAndCallAjax('POST', arguments);
            },

            put: function (params) {
                if (arguments.length == 1 && _o_.compare.isJsonObject(params))
                    _o_.ajax.request(params);

                else
                    internal.parseAndCallAjax('PUT', arguments);
            },

            delete: function (params) {
                if (arguments.length == 1 && _o_.compare.isJsonObject(params))
                    _o_.ajax.request(params);

                else
                    internal.parseAndCallAjax('DELETE', arguments);
            },

            patch: function (params) {
                if (arguments.length == 1 && _o_.compare.isJsonObject(params))
                    _o_.ajax.request(params);

                else
                    internal.parseAndCallAjax('PATCH', arguments);
            }
        });
    }
})(window);<commit_msg>cleansing unused syntax syntax<commit_after>/*
 === octapushJS.pluginName ===
 Author  : Fadhly Permata
 eMail   : fadhly.permata@gmail.com
 URL     : www.octapush.com

 === Credits ===
 Prime Developer : Fadhly Permata

 === Contributors ===
 ... just type your name here after editing the script ...

 === THANKS TO : ===
 - CORS Handling : Monsur Hossain (https://www.html5rocks.com/en/tutorials/cors/)
 - https://www.w3.org/
 - MDN : https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
 */

/**
 * NOTE:
 * - CORS test URL: http://html5rocks-cors.s3-website-us-east-1.amazonaws.com/index.html
 * - RESTFULL test URL: https://reqres.in/api/users
 */

(function (w) {
    'use strict';
    if (!w.octapushJS || !w._o_) {
        alert('octapushJS.ajax has dependency with "octapush.js". Please add the file first.');
        return;

    } else {
        const version = '1.7.02.21';

        var internal = {
            parseAndCallAjax: function (method, params) {
                var data = null;
                var success = null;

                if (!_o_.compare.isNullOrEmpty(params[1]) && !_o_.compare.isFunction(params[1]))
                    data = params[1];

                if (!_o_.compare.isNullOrEmpty(params[1]) && _o_.compare.isFunction(params[1]))
                    success = params[1];
                else {
                    success = params[2];
                }

                params = {
                    url: params[0],
                    data: data || null,
                    method: method,
                    success: success || null
                };

                _o_.ajax.request(params);
            }
        };

        _o_.ajax = Object.assign(_o_.utility.ifNull(_o_.ajax, {}), {
            request: function (params) {
                if (_o_.compare.isNullOrEmpty(params) || _o_.compare.isNullOrEmpty(params.url)) return;

                params = {
                    url: params.url || null,
                    data: params.data || null,
                    method: _o_.utility.ifNull(params.method, 'GET'),
                    success: params.success || null,
                    error: params.error || null,
                    headers: params.headers || {},
                    withCredentials: params.withCredentials || false
                };

                var xhr = null;

                // BOF: CROSS BROWSER SUPPORT
                // Chrome/Firefox/Opera/Safari/IE10+
                if (_o_.compare.isDefined(_o_.utility.getType(XMLHttpRequest))) {
                    xhr = new XMLHttpRequest();

                } else {
                    // check for XDomainRequest object
                    if (_o_.compare.isDefined(_o_.getType(XDomainRequest))) {
                        xhr = new XDomainRequest();

                    } else {
                        version = [
                            "MSXML2.XmlHttp.6.0",
                            "MSXML2.XmlHttp.5.0",
                            "MSXML2.XmlHttp.4.0",
                            "MSXML2.XmlHttp.3.0",
                            "MSXML2.XmlHttp.2.0",
                            "Microsoft.XmlHttp"
                        ];

                        // create xhr using higher version
                        for (var i = 0; i < version.length; i++) {
                            try {

                            } catch (e) {
                                if (!_o_.compare.isNullOrEmpty(params.error) && _o_.compare.isFunction(params.error))
                                    params.error(e);
                            }
                        }
                    }
                }
                // EOF: CROSS BROWSER SUPPORT

                if (params.method.toLowerCase() === 'get')
                    params.url = params.url + (_o_.compare.isNullOrEmpty(params.data) ? '' : '?' + params.data);

                xhr.open(params.method, params.url, true);

                // use credentials
                xhr.withCredentials = params.withCredentials;

                // set headers (preflight mode)
                _o_.utility.each(params.headers, function (key, val) {
                    if (val)
                        xhr.setRequestHeader(key, val);
                });

                xhr.send(params.method.toLowerCase() === 'get' ? null : params.data);

                xhr.onreadystatechange = function () {
                    if (xhr.readyState === XMLHttpRequest.DONE) {
                        if (xhr.status === 200 || xhr.status === 201 || xhr.status === 200) {
                            if (!_o_.compare.isNullOrEmpty(params.success) && _o_.compare.isFunction(params.success))
                                params.success(xhr);

                        } else {
                            if (!_o_.compare.isNullOrEmpty(params.error) && _o_.compare.isFunction(params.error))
                                params.error(xhr);
                        }
                    }
                };
            },

            // function (url, data, success)
            get: function (params) {
                if (arguments.length == 1 && _o_.compare.isJsonObject(params))
                    _o_.ajax.request(params);

                else
                    internal.parseAndCallAjax('GET', arguments);
            },

            // function (url, data, success)
            post: function (params) {
                if (arguments.length == 1 && _o_.compare.isJsonObject(params))
                    _o_.ajax.request(params);

                else
                    internal.parseAndCallAjax('POST', arguments);
            },

            put: function (params) {
                if (arguments.length == 1 && _o_.compare.isJsonObject(params))
                    _o_.ajax.request(params);

                else
                    internal.parseAndCallAjax('PUT', arguments);
            },

            delete: function (params) {
                if (arguments.length == 1 && _o_.compare.isJsonObject(params))
                    _o_.ajax.request(params);

                else
                    internal.parseAndCallAjax('DELETE', arguments);
            },

            patch: function (params) {
                if (arguments.length == 1 && _o_.compare.isJsonObject(params))
                    _o_.ajax.request(params);

                else
                    internal.parseAndCallAjax('PATCH', arguments);
            }
        });
    }
})(window);<|endoftext|>


<commit_before>import { graphql } from "react-apollo";
import { gql } from "react-apollo";
import pluralize from "pluralize";
import { get, upperFirst, camelCase } from "lodash";
import React from "react";
import deepEqual from "deep-equal";
import compose from "lodash/fp/compose";

/**
 * withQuery
 * @param {gql fragment} fragment supply a fragment as the first argument
 * @param {options} options
 * @typedef {object} options
 * @property {boolean} isPlural Are we searching for 1 thing or many?
 * @property {string} queryName What the props come back on ( by default = modelName + 'Query')
 * @property {boolean} asFunction If true, this gives you back a function you can call directly instead of a HOC
 * @property {boolean} asQueryObj If true, this gives you back the gql query object aka gql`query myQuery () {}`
 * @property {string} idAs By default single record queries occur on an id. But, if the record doesn't have an id field, and instead has a 'code', you can set idAs: 'code'
 * @property {boolean} getIdFromParams Grab the id variable off the match.params object being passed in!
 * @property {boolean} showLoading Show a loading spinner over the whole component while the data is loading
 * @property {boolean} showError Default=true show an error message toastr if the an error occurs while loading the data
 * @return {props}: {xxxxQuery, data }
 */

export default function withQuery(fragment, options = {}) {
  const {
    isPlural,
    queryName,
    nameOverride,
    argsOverride,
    asFunction,
    asQueryObj,
    idAs,
    LoadingComp,
    client,
    variables,
    props,
    getIdFromParams,
    showLoading,
    showError = true,
    ...rest
  } = options;
  if (typeof fragment === "string" || typeof fragment !== "object") {
    throw new Error("");
  }
  const name = get(fragment, "definitions[0].typeCondition.name.value");
  if (!name) {
    console.error("Bad fragment passed to withQuery!!");
    console.error(fragment, options);
    throw new Error(
      "No fragment name found in withQuery() call. This is due to passing in a string or something other than a gql fragment to withQuery"
    );
  }
  // const {fragment, extraMutateArgs} = options
  const fragName = fragment && fragment.definitions[0].name.value;
  const nameToUse = nameOverride || (isPlural ? pluralize(name) : name);
  const queryNameToUse = queryName || nameToUse + "Query";
  // const pascalNameToUse = pascalCase(nameToUse)
  let queryInner = `${fragName ? `...${fragName}` : idAs || "id"}`;
  if (isPlural) {
    queryInner = `results {
      ${queryInner}
    }
    totalResults`;
  }

  /* eslint-disable */
  let gqlQuery;
  if (argsOverride) {
    gqlQuery = gql`
    query ${queryNameToUse} ${argsOverride[0] || ""} {
      ${nameToUse} ${argsOverride[1] || ""} {
        ${queryInner}
      }
    }
    ${fragment ? fragment : ``}
  `;
  } else if (isPlural) {
    gqlQuery = gql`
      query ${queryNameToUse} ($pageSize: Int $sort: [String] $filter: JSON $pageNumber: Int) {
        ${nameToUse}(pageSize: $pageSize, sort: $sort, filter: $filter, pageNumber: $pageNumber) {
          ${queryInner}
        }
      }
      ${fragment ? fragment : ``}
    `;
  } else {
    gqlQuery = gql`
      query ${queryNameToUse} ($${idAs || "id"}: String!) {
        ${nameToUse}(${idAs || "id"}: $${idAs || "id"}) {
          ${queryInner}
        }
      }
      ${fragment ? fragment : ``}
    `;
  }

  /* eslint-enable */
  if (asQueryObj) {
    return gqlQuery;
  }
  if (asFunction) {
    return function query(localVars) {
      return client
        .query({
          query: gqlQuery,
          name: "createDataFile",
          variables:
            localVars ||
            variables ||
            (rest.options && rest.options.variables) ||
            undefined
        })
        .then(function(res) {
          return Promise.resolve(
            isPlural ? res.data[nameToUse].results : res.data[nameToUse],
            res.data,
            res
          );
        });
    };
  }

  return compose(
    graphql(gqlQuery, {
      //default options

      options: props => {
        const {
          variables,
          fetchPolicy,
          pollInterval,
          notifyOnNetworkStatusChange
        } = props;
        if (getIdFromParams) {
          const id = parseInt(get(props, "match.params.id"), 10);
          if (!id) {
            console.error(
              "There needs to be an id passed here to ",
              queryNameToUse,
              "but none was found"
            );
            /* eslint-disable */
            debugger;
            /* eslint-enable */
          }
          return {
            variables: {
              id
            },
            fetchPolicy,
            pollInterval,
            notifyOnNetworkStatusChange
          };
        }
        return {
          variables,
          fetchPolicy,
          pollInterval,
          notifyOnNetworkStatusChange
        };
      },
      props: (...args) => {
        const { data, ownProps } = args[0];
        const { tableParams } = ownProps;
        const results = get(data, nameToUse + (isPlural ? ".results" : ""));
        const totalResults = isPlural
          ? get(data, nameToUse + ".totalResults", 0)
          : results && 1;
        const newData = {
          ...data,
          totalResults,
          //adding these for consistency with withItemsQuery
          entities: results,
          entityCount: totalResults,
          ["error" + upperFirst(nameToUse)]: data.error,
          ["loading" + upperFirst(nameToUse)]: data.loading
        };

        return {
          ...(tableParams && !tableParams.entities
            ? {
                tableParams: {
                  ...tableParams,
                  isLoading: data.loading,
                  entities: results,
                  entityCount: totalResults,
                  onRefresh: data.refetch
                }
              }
            : {}),
          ...(props ? props(...args) : {}),
          data: newData,
          [queryNameToUse]: newData,
          [nameToUse]: results,
          [nameToUse + "Error"]: data.error,
          [nameToUse + "Loading"]: data.loading,
          [nameToUse + "Count"]: totalResults,
          [camelCase("refetch_" + nameToUse)]: data.refetch
        };
      },
      ...rest //overwrite defaults here
    }),
    function WithLoadingHOC(WrappedComponent) {
      return class WithLoadingComp extends React.Component {
        componentWillReceiveProps(nextProps) {
          if (
            showError &&
            nextProps.data &&
            this.props.data &&
            !deepEqual(nextProps.data.error, this.props.data.error)
          ) {
            const error = nextProps.data.error;
            console.error("error:", error);
            window.toastr.error(`Error loading ${queryNameToUse}`);
          }
        }
        render() {
          const { data = {} } = this.props;
          const { loading } = data;
          if (loading && showLoading) {
            return <LoadingComp loading />;
          }
          return <WrappedComponent {...this.props} />;
        }
      };
    }
  );
}
<commit_msg>spreading options on withQuery asFunction<commit_after>import { graphql } from "react-apollo";
import { gql } from "react-apollo";
import pluralize from "pluralize";
import { get, upperFirst, camelCase } from "lodash";
import React from "react";
import deepEqual from "deep-equal";
import compose from "lodash/fp/compose";

/**
 * withQuery
 * @param {gql fragment} fragment supply a fragment as the first argument
 * @param {options} options
 * @typedef {object} options
 * @property {boolean} isPlural Are we searching for 1 thing or many?
 * @property {string} queryName What the props come back on ( by default = modelName + 'Query')
 * @property {boolean} asFunction If true, this gives you back a function you can call directly instead of a HOC
 * @property {boolean} asQueryObj If true, this gives you back the gql query object aka gql`query myQuery () {}`
 * @property {string} idAs By default single record queries occur on an id. But, if the record doesn't have an id field, and instead has a 'code', you can set idAs: 'code'
 * @property {boolean} getIdFromParams Grab the id variable off the match.params object being passed in!
 * @property {boolean} showLoading Show a loading spinner over the whole component while the data is loading
 * @property {boolean} showError Default=true show an error message toastr if the an error occurs while loading the data
 * @return {props}: {xxxxQuery, data }
 */

export default function withQuery(fragment, options = {}) {
  const {
    isPlural,
    queryName,
    nameOverride,
    argsOverride,
    asFunction,
    asQueryObj,
    idAs,
    LoadingComp,
    client,
    variables,
    props,
    getIdFromParams,
    showLoading,
    showError = true,
    ...rest
  } = options;
  if (typeof fragment === "string" || typeof fragment !== "object") {
    throw new Error("");
  }
  const name = get(fragment, "definitions[0].typeCondition.name.value");
  if (!name) {
    console.error("Bad fragment passed to withQuery!!");
    console.error(fragment, options);
    throw new Error(
      "No fragment name found in withQuery() call. This is due to passing in a string or something other than a gql fragment to withQuery"
    );
  }
  // const {fragment, extraMutateArgs} = options
  const fragName = fragment && fragment.definitions[0].name.value;
  const nameToUse = nameOverride || (isPlural ? pluralize(name) : name);
  const queryNameToUse = queryName || nameToUse + "Query";
  // const pascalNameToUse = pascalCase(nameToUse)
  let queryInner = `${fragName ? `...${fragName}` : idAs || "id"}`;
  if (isPlural) {
    queryInner = `results {
      ${queryInner}
    }
    totalResults`;
  }

  /* eslint-disable */
  let gqlQuery;
  if (argsOverride) {
    gqlQuery = gql`
    query ${queryNameToUse} ${argsOverride[0] || ""} {
      ${nameToUse} ${argsOverride[1] || ""} {
        ${queryInner}
      }
    }
    ${fragment ? fragment : ``}
  `;
  } else if (isPlural) {
    gqlQuery = gql`
      query ${queryNameToUse} ($pageSize: Int $sort: [String] $filter: JSON $pageNumber: Int) {
        ${nameToUse}(pageSize: $pageSize, sort: $sort, filter: $filter, pageNumber: $pageNumber) {
          ${queryInner}
        }
      }
      ${fragment ? fragment : ``}
    `;
  } else {
    gqlQuery = gql`
      query ${queryNameToUse} ($${idAs || "id"}: String!) {
        ${nameToUse}(${idAs || "id"}: $${idAs || "id"}) {
          ${queryInner}
        }
      }
      ${fragment ? fragment : ``}
    `;
  }

  /* eslint-enable */
  if (asQueryObj) {
    return gqlQuery;
  }
  if (asFunction) {
    return function query(localVars) {
      return client
        .query({
          query: gqlQuery,
          name: "createDataFile",
          ...(rest.options ? rest.options : {}),
          variables:
            localVars ||
            variables ||
            (rest.options && rest.options.variables) ||
            undefined
        })
        .then(function(res) {
          return Promise.resolve(
            isPlural ? res.data[nameToUse].results : res.data[nameToUse],
            res.data,
            res
          );
        });
    };
  }

  return compose(
    graphql(gqlQuery, {
      //default options

      options: props => {
        const {
          variables,
          fetchPolicy,
          pollInterval,
          notifyOnNetworkStatusChange
        } = props;
        if (getIdFromParams) {
          const id = parseInt(get(props, "match.params.id"), 10);
          if (!id) {
            console.error(
              "There needs to be an id passed here to ",
              queryNameToUse,
              "but none was found"
            );
            /* eslint-disable */
            debugger;
            /* eslint-enable */
          }
          return {
            variables: {
              id
            },
            fetchPolicy,
            pollInterval,
            notifyOnNetworkStatusChange
          };
        }
        return {
          variables,
          fetchPolicy,
          pollInterval,
          notifyOnNetworkStatusChange
        };
      },
      props: (...args) => {
        const { data, ownProps } = args[0];
        const { tableParams } = ownProps;
        const results = get(data, nameToUse + (isPlural ? ".results" : ""));
        const totalResults = isPlural
          ? get(data, nameToUse + ".totalResults", 0)
          : results && 1;
        const newData = {
          ...data,
          totalResults,
          //adding these for consistency with withItemsQuery
          entities: results,
          entityCount: totalResults,
          ["error" + upperFirst(nameToUse)]: data.error,
          ["loading" + upperFirst(nameToUse)]: data.loading
        };

        return {
          ...(tableParams && !tableParams.entities
            ? {
                tableParams: {
                  ...tableParams,
                  isLoading: data.loading,
                  entities: results,
                  entityCount: totalResults,
                  onRefresh: data.refetch
                }
              }
            : {}),
          ...(props ? props(...args) : {}),
          data: newData,
          [queryNameToUse]: newData,
          [nameToUse]: results,
          [nameToUse + "Error"]: data.error,
          [nameToUse + "Loading"]: data.loading,
          [nameToUse + "Count"]: totalResults,
          [camelCase("refetch_" + nameToUse)]: data.refetch
        };
      },
      ...rest //overwrite defaults here
    }),
    function WithLoadingHOC(WrappedComponent) {
      return class WithLoadingComp extends React.Component {
        componentWillReceiveProps(nextProps) {
          if (
            showError &&
            nextProps.data &&
            this.props.data &&
            !deepEqual(nextProps.data.error, this.props.data.error)
          ) {
            const error = nextProps.data.error;
            console.error("error:", error);
            window.toastr.error(`Error loading ${queryNameToUse}`);
          }
        }
        render() {
          const { data = {} } = this.props;
          const { loading } = data;
          if (loading && showLoading) {
            return <LoadingComp loading />;
          }
          return <WrappedComponent {...this.props} />;
        }
      };
    }
  );
}
<|endoftext|>


<commit_before>import StyleSheet from './StyleSheet'
import cssifyCache from './utils/cssifyCache'

export default class Renderer {
  constructor(config) {
    this.stylesheet = new StyleSheet(config)
  }

  /**
   * renders selector or Keyframe variations, FontFaces and static styles
   * to an intern StyleSheet that caches those for future use
   *
   * @param {Function|Keyframe|FontFace|string|Object} element - selector, Keyframe, FontFace or static styles
   * @param {Object?} props - list of props to render
   * @param {Function[]?} plugins - array of plugins to process styles
   * @return {string} className, animation name, font family
   */
  render(element, props, plugins) {
    return this.stylesheet.handleRender(element, props, plugins)
  }

  /**
   * renders all cached selector styles into a single valid CSS string
   * clusters media query styles into groups to reduce output size

   * @return single concatenated CSS string
   */
  renderToString() {
    let css = ''

    this.stylesheet.fontFaces.forEach(markup => css += markup)
    this.stylesheet.statics.forEach(markup => css += markup)
    css += cssifyCache(this.stylesheet.cache)
    this.stylesheet.mediaCache.forEach((cache, media) => {
      css += '@media ' + media + '{' + cssifyCache(cache) + '}'
    })
    this.stylesheet.keyframes.forEach(variation => {
      variation.forEach(markup => css += markup)
    })

    return css
  }

  /**
   * clears the stylesheet
   */
  clear() {
    this.stylesheet.clear()
  }
}
<commit_msg>Bind `render` for server renderer too<commit_after>import StyleSheet from './StyleSheet'
import cssifyCache from './utils/cssifyCache'

export default class Renderer {
  constructor(config) {
    this.stylesheet = new StyleSheet(config)
  }

  /**
   * renders selector or Keyframe variations, FontFaces and static styles
   * to an intern StyleSheet that caches those for future use
   *
   * @param {Function|Keyframe|FontFace|string|Object} element - selector, Keyframe, FontFace or static styles
   * @param {Object?} props - list of props to render
   * @param {Function[]?} plugins - array of plugins to process styles
   * @return {string} className, animation name, font family
   */
  render = (element, props, plugins) => {
    return this.stylesheet.handleRender(element, props, plugins)
  }

  /**
   * renders all cached selector styles into a single valid CSS string
   * clusters media query styles into groups to reduce output size

   * @return single concatenated CSS string
   */
  renderToString() {
    let css = ''

    this.stylesheet.fontFaces.forEach(markup => css += markup)
    this.stylesheet.statics.forEach(markup => css += markup)
    css += cssifyCache(this.stylesheet.cache)
    this.stylesheet.mediaCache.forEach((cache, media) => {
      css += '@media ' + media + '{' + cssifyCache(cache) + '}'
    })
    this.stylesheet.keyframes.forEach(variation => {
      variation.forEach(markup => css += markup)
    })

    return css
  }

  /**
   * clears the stylesheet
   */
  clear() {
    this.stylesheet.clear()
  }
}
<|endoftext|>


<commit_before>
/**
 * OAuth 2.0 request validation.
 *
 * This component provides a function that validates a client's authorization
 * request.  If the request is valid, the function yeilds a `client` object and
 * a `redirectURI`.  The client object provides metadata about the client, such
 * as name and logo, used during processing of the authorization request.  The
 * redirect URI is used when responding to the authorization request via HTTP
 * redirections.
 *
 * If the request is invalid, the function yeilds an error.  It is expected that
 * the application will inform the user of the error, and must not automatically
 * redirect the user to an invalid redirection URI.
 */

exports = module.exports = function(evaluate, clients, server, authenticate, state, session, parseCookies, logger, C) {
  var oauth2orize = require('oauth2orize')
    , url = require('url');

  return Promise.resolve(null)
    .then(function() {
      var schemes = {};

      return new Promise(function(resolve, reject) {
        var components = C.components('http://i.authnomicon.org/oauth2/authorization/http/RedirectURIScheme')
          , key;

        (function iter(i) {
          var component = components[i];
          if (!component) {
            return resolve(schemes);
          }

          key = component.a['@scheme'];

          component.create()
            .then(function(mode) {
              logger.info("Loaded redirect URI scheme '" + key +  "'");
              schemes[key] = mode;
              iter(i + 1);
            }, function(err) {
              var msg = 'Failed to load redirect URI scheme:\n';
              msg += err.stack;
              logger.warning(msg);
              return iter(i + 1);
            })
        })(0);
      });
    })
    .then(function(schemes) {

      return [
        parseCookies(),
        session(),
        state({ external: true }),
        authenticate([ 'session', 'anonymous' ], { multi: true }),
        server.authorization(
          function validateClient(clientID, redirectURI, cb) {

            clients.read(clientID, function(err, client) {
              if (err) { return cb(err); }
              if (!client) {
                return cb(new oauth2orize.AuthorizationError('Unauthorized client', 'unauthorized_client'));
              }

              if (!client.redirectURIs || !client.redirectURIs.length) {
                // The client has not registered any redirection endpoints.  Such
                // clients are not authorized to use the authorization endpoint.
                //
                // This enforcement is in place in order to prevent the authorization
                // server from functioning as an open redirector.  Refer to Section
                // 3.1.2.2 of RFC 6749 for further details.
                return cb(new oauth2orize.AuthorizationError('Client has no registered redirect URIs', 'unauthorized_client'));
              }
              if (client.redirectURIs.length > 1 && !redirectURI) {
                // If multiple redirection URIs have been registered, the client must
                // include a redirection URI with the authorization request.  Refer to
                // Section 3.1.2.3 of RFC 6749 for further details.
                return cb(new oauth2orize.AuthorizationError('Missing required parameter: redirect_uri', 'invalid_request'));
              }

              var ruri = redirectURI || client.redirectURIs[0];

              var uri = url.parse(ruri);
              var proto = uri.protocol.slice(0, -1);
              var scheme = schemes[proto];
              var v;

              if (scheme) {
                v = scheme.verify(client, redirectURI);
                if (!v) {
                  return cb(new oauth2orize.AuthorizationError('Client not permitted to use redirect URI', 'unauthorized_client'));
                }

                return cb(null, client, v[0], v[1]);
              }

              // WIP
              /*
              // http://lists.openid.net/pipermail/openid-specs-ab/Week-of-Mon-20151116/005865.html
              if (redirectURI) {
                var url = uri.parse(redirectURI);
                //console.log(url);
                if (url.protocol == 'storagerelay:') {
                  // TODO: Implement web/js origin checks
                  return cb(null, client, redirectURI, 'http://localhost:3001');
                }
              }
              */

              if (redirectURI && client.redirectURIs.indexOf(redirectURI) == -1) {
                return cb(new oauth2orize.AuthorizationError('Client not permitted to use redirect URI', 'unauthorized_client'));
              }

              return cb(null, client, redirectURI || client.redirectURIs[0]);
            }); // clients.read
          },
          function(txn, cb) {
            // TODO: Filter out "internal" response modes by erroring here?

            // Immediate mode callback.  Always, false, deferring transaction processing to
            // HTTP handler below where all context is available.
            return cb(null, false);
          }
        ),
        evaluate,
        // TODO: Add error handling middleware here
        // TODO: Check that this is right and not reloading the txn
        server.authorizationError()
      ];

  });
};

exports['@require'] = [
  '../middleware/evaluate',
  'http://i.authnomicon.org/oauth2/ClientDirectory',
  '../../../http/server',
  'http://i.bixbyjs.org/http/middleware/authenticate',
  'http://i.bixbyjs.org/http/middleware/state',
  'http://i.bixbyjs.org/http/middleware/session',
  'http://i.bixbyjs.org/http/middleware/parseCookies',
  'http://i.bixbyjs.org/Logger',
  '!container'
];
<commit_msg>Clean up.<commit_after>
/**
 * OAuth 2.0 request validation.
 *
 * This component provides a function that validates a client's authorization
 * request.  If the request is valid, the function yeilds a `client` object and
 * a `redirectURI`.  The client object provides metadata about the client, such
 * as name and logo, used during processing of the authorization request.  The
 * redirect URI is used when responding to the authorization request via HTTP
 * redirections.
 *
 * If the request is invalid, the function yeilds an error.  It is expected that
 * the application will inform the user of the error, and must not automatically
 * redirect the user to an invalid redirection URI.
 */

exports = module.exports = function(evaluate, clients, server, authenticate, state, session, parseCookies, logger, C) {
  var oauth2orize = require('oauth2orize')
    , url = require('url');

  return Promise.resolve(null)
    .then(function() {
      var schemes = {};

      return new Promise(function(resolve, reject) {
        var components = C.components('http://i.authnomicon.org/oauth2/authorization/http/RedirectURIScheme')
          , key;

        (function iter(i) {
          var component = components[i];
          if (!component) {
            return resolve(schemes);
          }

          key = component.a['@scheme'];

          component.create()
            .then(function(mode) {
              logger.info("Loaded redirect URI scheme '" + key +  "'");
              schemes[key] = mode;
              iter(i + 1);
            }, function(err) {
              var msg = 'Failed to load redirect URI scheme:\n';
              msg += err.stack;
              logger.warning(msg);
              return iter(i + 1);
            })
        })(0);
      });
    })
    .then(function(schemes) {

      return [
        parseCookies(),
        session(),
        state({ external: true }),
        authenticate([ 'session', 'anonymous' ], { multi: true }),
        server.authorization(
          function validateClient(clientID, redirectURI, cb) {

            clients.read(clientID, function(err, client) {
              if (err) { return cb(err); }
              if (!client) {
                return cb(new oauth2orize.AuthorizationError('Unauthorized client', 'unauthorized_client'));
              }

              if (!client.redirectURIs || !client.redirectURIs.length) {
                // The client has not registered any redirection endpoints.  Such
                // clients are not authorized to use the authorization endpoint.
                //
                // This enforcement is in place in order to prevent the authorization
                // server from functioning as an open redirector.  Refer to Section
                // 3.1.2.2 of RFC 6749 for further details.
                return cb(new oauth2orize.AuthorizationError('Client has no registered redirect URIs', 'unauthorized_client'));
              }
              if (client.redirectURIs.length > 1 && !redirectURI) {
                // If multiple redirection URIs have been registered, the client must
                // include a redirection URI with the authorization request.  Refer to
                // Section 3.1.2.3 of RFC 6749 for further details.
                return cb(new oauth2orize.AuthorizationError('Missing required parameter: redirect_uri', 'invalid_request'));
              }

              var ruri = redirectURI || client.redirectURIs[0]
                , uri = url.parse(ruri)
                , proto = uri.protocol.slice(0, -1)
                , scheme = schemes[proto], v;

              if (scheme) {
                v = scheme.verify(client, ruri);
                if (!v) {
                  return cb(new oauth2orize.AuthorizationError('Client not permitted to use redirect URI', 'unauthorized_client'));
                }
                return cb(null, client, v[0], v[1]);
              }

              if (redirectURI && client.redirectURIs.indexOf(redirectURI) == -1) {
                return cb(new oauth2orize.AuthorizationError('Client not permitted to use redirect URI', 'unauthorized_client'));
              }

              return cb(null, client, ruri);
            }); // clients.read
          },
          function(txn, cb) {
            // TODO: Filter out "internal" response modes by erroring here?

            // Immediate mode callback.  Always, false, deferring transaction processing to
            // HTTP handler below where all context is available.
            return cb(null, false);
          }
        ),
        evaluate,
        // TODO: Add error handling middleware here
        // TODO: Check that this is right and not reloading the txn
        server.authorizationError()
      ];

  });
};

exports['@require'] = [
  '../middleware/evaluate',
  'http://i.authnomicon.org/oauth2/ClientDirectory',
  '../../../http/server',
  'http://i.bixbyjs.org/http/middleware/authenticate',
  'http://i.bixbyjs.org/http/middleware/state',
  'http://i.bixbyjs.org/http/middleware/session',
  'http://i.bixbyjs.org/http/middleware/parseCookies',
  'http://i.bixbyjs.org/Logger',
  '!container'
];
<|endoftext|>


<commit_before>#!/usr/bin/env node

const path = require('path')
const fs = require('fs')
const walk = require('walk')
const colors = require('colors')

const template = __dirname + '/../template'
const config = require('../lib/config')
const exists = require('../lib/etc').exists

if (path.basename(process.cwd()) == 'template') {
  console.log('You shouldn\'t run ' + 'init'.gray + ' in here.')
  console.log('Please run it somewhere outside of the project.')
  process.exit(0)
}

const walker = walk.walk(template, {
  filters: [path.parse(config.outputDir).base]
})

walker.on('file', function (root, fileStats, next) {
  const way = root + '/' + fileStats.name
  const subPath = root.replace(template, '')
  const folder = process.cwd() + subPath

  if (!exists(folder)) {
    fs.mkdirSync(folder)
  }

  const targetPath = process.cwd() +  '/' + subPath + '/' + fileStats.name
  const target = fs.createWriteStream(targetPath)

  fs.createReadStream(way).pipe(target)
  next()
})

walker.on('end', function() {
  console.log('Generated new site in ' + process.cwd().gray)
})
<commit_msg>Log errors when piping files<commit_after>#!/usr/bin/env node

const path = require('path')
const fs = require('fs')
const walk = require('walk')
const colors = require('colors')

const template = __dirname + '/../template'
const config = require('../lib/config')
const exists = require('../lib/etc').exists

if (path.basename(process.cwd()) == 'template') {
  console.log('You shouldn\'t run ' + 'init'.gray + ' in here.')
  console.log('Please run it somewhere outside of the project.')
  process.exit(0)
}

const walker = walk.walk(template, {
  filters: [path.parse(config.outputDir).base]
})

walker.on('file', function (root, fileStats, next) {
  const way = root + '/' + fileStats.name
  const subPath = root.replace(template, '')
  const folder = process.cwd() + subPath

  if (!exists(folder)) {
    fs.mkdirSync(folder)
  }

  const targetPath = process.cwd() +  '/' + subPath + '/' + fileStats.name
  const target = fs.createWriteStream(targetPath)

  const original = fs.createReadStream(way).pipe(target)

  target.on('error', console.error)
  original.on('error', console.error)

  next()
})

walker.on('end', function() {
  console.log('Generated new site in ' + process.cwd().gray)
})
<|endoftext|>


<commit_before>#!/usr/bin/env node

// simple testing utility to take any link json on STDIN and try to link to it, then exit on success/error

var telehash = require('../lib/mesh.js');
telehash.add(require('telehash-udp4'));
var readline = require('readline');

var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

function error(err)
{
  console.error(err);
  process.exit(1);
}

telehash.generate(function(err, id){
  if(err) return error(err);
  telehash.mesh({id:id}, function(err, mesh){
    if(err) return error(err);
    if(process.argv[2]) mesh.link(process.argv[2]);
    rl.on('line', function(line){
      var link = mesh.link(JSON.parse(line));
      link.status(function(err){
        if(err) return error(err);
        process.exit(0);
      });
      setTimeout(function(){error('timeout')},1000);
    });
  });
});

<commit_msg>just enabling link test debug by default<commit_after>#!/usr/bin/env node

// simple testing utility to take any link json on STDIN and try to link to it, then exit on success/error

var telehash = require('../lib/mesh.js');
telehash.add(require('telehash-udp4'));
var readline = require('readline');

var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

function error(err)
{
  console.error(err);
  process.exit(1);
}

telehash.log({debug:console.log});

telehash.generate(function(err, id){
  if(err) return error(err);
  telehash.mesh({id:id}, function(err, mesh){
    if(err) return error(err);
    if(process.argv[2]) mesh.link(process.argv[2]);
    rl.on('line', function(line){
      var link = mesh.link(JSON.parse(line));
      link.status(function(err){
        if(err) return error(err);
        process.exit(0);
      });
      setTimeout(function(){error('timeout')},1000);
    });
  });
});

<|endoftext|>


<commit_before>#!/usr/bin/env node

const fs = require('fs');

//获取命令内容
let [nodePath, mainPath, command, ...parameters] = process.argv;
//转换 linux 下软链接路径为真实路径
mainPath = fs.realpathSync(mainPath);

// co 模块，异步函数编程
const co = require('../modules/co');

//在全局变量上绑定 alert、confirm2、prompt2 方法，作为命令行输出与交互
({alert: global.alert, confirm2: global.confirm2, prompt2: global.prompt2} = require('./messageBox'));

// wiki 创建器
const creator = require('../build/creator');
//文库管理
const mngWiki = require('../build/manageWiki');
//文件夹管理
const mngFolder = require('../build/manageFolder');
//手动刷新导航文件
const makeNav = require('../build/makeNavigation');
//本地服务器模块
const localServer = require('../build/localServer');
//项目导出模块
const exportGithub = require('../build/exportGithub');

//格式化显示
const printFn = require('./printf');

//项目根目录
const root = mngFolder.isAmWiki(process.cwd());
const wikis = {};

co(function*() {

    //执行命令
    switch (command) {
        //依据引导创建 wiki
        case 'init':
            break;
        //依据 config.json 创建 wiki
        case 'create':
        case '-c':
            // config.json 文件路径
            const configPath = process.cwd().replace(/\\/g, '/') + '/config.json';
            //项目 files 文件夹路径
            const filesPath = mainPath.replace(/\\/g, '/').split('bin')[0] + 'files/';
            //开始创建
            const root2 = yield creator.create(configPath, filesPath);
            //更新导航
            makeNav.refresh(root2 + 'library/');
            break;
        //更新 wiki
        case 'update':
        case '-u':
            if (!root) {
                console.error('非amWiki项目文件夹，无法更新导航！');
                break;
            }
            const type = parameters[0];
            //更新导航
            if (type === 'nav') {
                makeNav.refresh(root);
            }
            //更新文库嵌入数据
            else if (type === 'embed') {
            }
            //更新 SEO 模块
            else if (type === 'seo') {
            }
            //完整更新
            else if (typeof type === 'undefined') {
                makeNav.refresh(root);
            }
            break;
        //启动本地服务器
        case 'server':
        case '-s':
            if (!root) {
                console.error('非amWiki项目文件夹，无法启动服务器！');
                break;
            }
            mngWiki.linkWikis(wikis);
            mngWiki.addWiki(root);
            const port = parameters[0];
            //有输入端口且合法
            if (typeof port !== 'undefined' && /^\d+$/.test(port)) {
                localServer.run(wikis, port);
            }
            //没输入端口号
            else {
                localServer.run(wikis);
            }
            break;
        //本地浏览文档
        case 'browser':
        case '-b':
            if (!root) {
                console.error('非amWiki项目文件夹，无法浏览文库！');
                break;
            }
            mngWiki.linkWikis(wikis);
            mngWiki.addWiki(root);
            const fileId = parameters[0];
            //未给出需要浏览的文档id
            if (typeof fileId === 'undefined') {
                yield localServer.browser(root + 'library/', wikis);
            }
            //有给出需要浏览的文档id
            else {
            }
            break;
        //导出 wiki
        case 'export':
        case '-e':
            if (!root) {
                console.error('非amWiki项目文件夹，无法导出！');
                break;
            }
            if (parameters[0] !== 'github-wiki') {
                console.error('除 github-wiki 外，目前不支持其他类型导出！');
                break;
            }
            let outPath = parameters[1];
            if (typeof outPath === 'undefined') {
                outPath = yield prompt2('请输入导出文件夹：');
            }
            outPath = outPath.replace(/\\/g, '/');
            yield exportGithub.export(root, outPath);
            break;
        //显示版本号
        case 'version':
        case '-v':
            printFn.ver(mainPath);
            break;
        //显示帮助
        case 'help':
        case '-h':
        default:
            printFn.help();
            break;

    }

    //关闭用户输入
    process.stdin.end();

}).catch((e) => {
    console.error(e);
});
<commit_msg>修复 windows 平台下 gitbash 所有命令结束时都报错的问题<commit_after>#!/usr/bin/env node

const fs = require('fs');

//获取命令内容
let [nodePath, mainPath, command, ...parameters] = process.argv;
//转换 linux 下软链接路径为真实路径
mainPath = fs.realpathSync(mainPath);

// co 模块，异步函数编程
const co = require('../modules/co');

//在全局变量上绑定 alert、confirm2、prompt2 方法，作为命令行输出与交互
({alert: global.alert, confirm2: global.confirm2, prompt2: global.prompt2} = require('./messageBox'));

// wiki 创建器
const creator = require('../build/creator');
//文库管理
const mngWiki = require('../build/manageWiki');
//文件夹管理
const mngFolder = require('../build/manageFolder');
//手动刷新导航文件
const makeNav = require('../build/makeNavigation');
//本地服务器模块
const localServer = require('../build/localServer');
//项目导出模块
const exportGithub = require('../build/exportGithub');

//格式化显示
const printFn = require('./printf');

//项目根目录
const root = mngFolder.isAmWiki(process.cwd());
const wikis = {};

co(function*() {

    //执行命令
    switch (command) {
        //依据引导创建 wiki
        case 'init':
            break;
        //依据 config.json 创建 wiki
        case 'create':
        case '-c':
            // config.json 文件路径
            const configPath = process.cwd().replace(/\\/g, '/') + '/config.json';
            //项目 files 文件夹路径
            const filesPath = mainPath.replace(/\\/g, '/').split('bin')[0] + 'files/';
            //开始创建
            const root2 = yield creator.create(configPath, filesPath);
            //更新导航
            makeNav.refresh(root2 + 'library/');
            break;
        //更新 wiki
        case 'update':
        case '-u':
            if (!root) {
                console.error('非amWiki项目文件夹，无法更新导航！');
                break;
            }
            const type = parameters[0];
            //更新导航
            if (type === 'nav') {
                makeNav.refresh(root);
            }
            //更新文库嵌入数据
            else if (type === 'embed') {
            }
            //更新 SEO 模块
            else if (type === 'seo') {
            }
            //完整更新
            else if (typeof type === 'undefined') {
                makeNav.refresh(root);
            }
            break;
        //启动本地服务器
        case 'server':
        case '-s':
            if (!root) {
                console.error('非amWiki项目文件夹，无法启动服务器！');
                break;
            }
            mngWiki.linkWikis(wikis);
            mngWiki.addWiki(root);
            const port = parameters[0];
            //有输入端口且合法
            if (typeof port !== 'undefined' && /^\d+$/.test(port)) {
                localServer.run(wikis, port);
            }
            //没输入端口号
            else {
                localServer.run(wikis);
            }
            break;
        //本地浏览文档
        case 'browser':
        case '-b':
            if (!root) {
                console.error('非amWiki项目文件夹，无法浏览文库！');
                break;
            }
            mngWiki.linkWikis(wikis);
            mngWiki.addWiki(root);
            const fileId = parameters[0];
            //未给出需要浏览的文档id
            if (typeof fileId === 'undefined') {
                yield localServer.browser(root + 'library/', wikis);
            }
            //有给出需要浏览的文档id
            else {
            }
            break;
        //导出 wiki
        case 'export':
        case '-e':
            if (!root) {
                console.error('非amWiki项目文件夹，无法导出！');
                break;
            }
            if (parameters[0] !== 'github-wiki') {
                console.error('除 github-wiki 外，目前不支持其他类型导出！');
                break;
            }
            let outPath = parameters[1];
            if (typeof outPath === 'undefined') {
                outPath = yield prompt2('请输入导出文件夹：');
            }
            outPath = outPath.replace(/\\/g, '/');
            yield exportGithub.export(root, outPath);
            break;
        //显示版本号
        case 'version':
        case '-v':
            printFn.ver(mainPath);
            break;
        //显示帮助
        case 'help':
        case '-h':
        default:
            printFn.help();
            break;

    }

    //关闭用户输入
    //process.stdin.end();
    process.exit();

}).catch((e) => {
    console.error(e);
});
<|endoftext|>