<commit_before>;(function() {
    var adv = new Adventure(document.getElementById('adventure'), 'start');

    function showEndMsg() {
        document.getElementById('endmsglink').href = 'https://wiki.mozilla.org/Webdev/Beer_And_Tell/December2013';
        document.getElementById('endmsg').className = 'show';
    }

    var intro = false;
    var hasAddon = false;
    adv.room('start', function() {
        if (!intro) {
            intro = true;
            adv.say("I can remember it like it was yesterday.");
            adv.say("It was a cold, rainy night. It always is. The story wouldn't be nearly as good if it happened on a sunny afternoon.");
            adv.say("I had known the client for years. She was a good friend; her family took me in when my own kicked me out. And even when I was on the streets, she was still there for me, giving me food and clothes, letting me stay on her couch when I wasn't out on the streets hustling for market share.");
            adv.say("It was a typical story: She was minding her own business, browsing a site someone had linked her to from an email, but she soon noticed some strange-looking ads. They seemed to know more about her than they should've, suggesting things like a present for her brother's birthday. How could they know that it was coming up?");
            adv.say("That's when she looked in her purse and noticed it: someone had slipper her a tracking cookie. And not just any tracking cookie, but an evercookie. The kind that you just can't get rid of.");
            adv.say("I had already given her Ghostery, which handled most other tracking cookies, but this one just wouldn't let go. I knew that we needed something different, and I knew where I could get it.");
            adv.say("I headed down to the Seventh Street webring. Browsers like me weren't always welcome down there; I saw a few 'Best Viewed with Internet Explorer 6' signs. Got a few glares, but I'd been through this dance before. I pulled out Quirks Mode, and people knew to leave me alone.");
        }

        var shop = "There was a closed-down user script shop near the entrance.";
        if (knowsWhereAddonIs && !hasAddon) {
            shop += " I noticed a small trashcan sitting outside the shop.";
        }

        adv.say("I was standing at the entrance to the Seventh Street webring. The dim lights reflected off the puddles in the alley. " + shop);
        adv.say("The alley continued north, deeper into the webring. South led back out the webring, but I still had business to take care of. Leaving then would've been nothing but trouble.");
    }, {
        north: 'outsideStore',
        south: 'utterFailure',
        extraCommands: {
            search: function(cmd) {
                if (cmd.indexOf('trash') === -1) {
                    adv.say("I couldn't find anything there. Maybe somewhere else?");
                } else if (hasAddon) {
                    adv.say("I searched the trash again, but couldn't find anything else useful");
                } else if (knowsWhereAddonIs) {
                    hasAddon = true;
                    adv.score += 100;
                    adv.say("I was no stranger to digging through the trash, and soon enough I found a beat-up looking addon. Just like the old browser said, it was a User-Agent spoofer. I configured it to mask me as Internet Explorer 6 and installed it.");
                } else {
                    adv.say("I didn't know what I was searching for, and couldn't find anything useful anyway.");
                }
            }
        },
        synonyms: {
            'examine': 'search',
            'look in': 'search',
            'check': 'search'
        },
    });

    adv.room('utterFailure', function() {
        adv.say("You think I'm the kind of guy who high-tails it when going gets tough? Buzz off! Get outta my face, you lowlife scum!");
        adv.endGame(true);
    });

    var outsideStoreFirstVisit = true;
    var triedToEnterStore = false;
    adv.room('outsideStore', function() {
        var extra = '';
        if (outsideStoreFirstVisit) {
            outsideStoreFirstVisit = false;
            adv.say("I moved deeper into the alleyway. The stench of <FONT>s wafted through the air. This place was bad news, but I'd seen worse.");
            adv.say("I stood in front of a badly-lit addon shop. This was where I needed to be; I had heard rumors the guy who ran this shop could find any addon. Obviously, this kind of service didn't come cheap.");
        } else {
            extra = "I was back outside the addon shop. ";
        }

        adv.say(extra + "I could've tried to enter the shop. North led further into the webring, while south led back to the webring entrance.");
    }, {
        south: 'start',
        north: 'outsideBar',
        extraCommands: {
            enter: function(cmd) {
                if (hasAddon) {
                    adv.say("This time, when I tried the door, it opened immediately. Finally, I could move on!");
                    adv.say("I walked into the store. The walls will filled with shelves stuffed with addons for almost anything you could imagine, from showing the prices for an item from other sites for comparison, to storing tabs in a tree-structure, to changing the menu icon into a hamburger.");
                    adv.say("As I headed to the back of the store, I heard an old man's voice call out to me. I saw a small man standing behind a counter waving to me. As I approached, I realized this was the merchant I had been told about. He was the one who could help me find an addon for my client.");
                    adv.say("So you're the one looking for an addon to get rid of an evercookie, eh?", 'potch');
                    adv.say("How do you know about that?", 'firefox');
                    adv.say("Young man, it's my business to know these things. How could I find an addon like this if I couldn't even find out a bit of news about you?", 'potch');
                    adv.say("But that doesn't matter. Seeing that you were able to get past my door, I'm willing to help you. You've proved to be a resourceful little browser, and I'm prepared to give you information on where to aquire this addon. In return, I expect you to do something for me.", 'potch');
                    adv.say("And what do you need me to do?", 'firefox');
                    adv.say("Hah! So eager! You need to relax, young man. What I want from you will be made clear later. For now, you should track down this addon for your client.", 'potch');
                    adv.prompt("He handed me a small business card and instructed me to visit the URL on the card to find what I was looking for. However, when I sent a request to the page, all I got back was a 302 redirect and a very odd response body that said...", function() {
                        showEndMsg();
                    });
                } else {
                    var firstBlock = !triedToEnterStore;

                    triedToEnterStore = true;
                    adv.score += 10;
                    adv.say("I tried to open the front door, but it wouldn't budge. When I pulled on the knob, a small message popped up in the window:");
                    adv.say("'We only support Internet Explorer 6'");
                    adv.say("It looked like the shop was actively blocking any User-Agent that didn't match IE6. I realized I'd need to fool the shop somehow before I could get in.");

                    if (firstBlock) {
                        adv.say("Lucky for me, I knew a guy who could help me out by the name of Mickey. At that hour he was usually hanging out at a bar down the webring a bit. I figured it'd be a good idea to pay him a visit.");
                    } else {
                        adv.say("I still needed to talk to Mickey about getting past the door.");
                    }
                }
            },
        },
        synonyms: {
            'open': 'enter',
        },
    });

    var outsideBarFirst = true;
    var talkedToHobo = false;
    var knowsWhereAddonIs = false;
    adv.room('outsideBar', function() {
        if (outsideBarFirst) {
            outsideBarFirst = false;
            adv.say("Near the back of the webring was a dingy bar. You could hear the awful auto-playing Midi music from the other end of the webring.");
            adv.say("I knew a guy by the name of Mickey who frequented the bar. Most nights you could find him in some corner, lying his head off about some recent startup or Facebook app he was working on. But for all his faults, he knew this part of town better than anyone.");

            adv.say("Outside the bar there were some old text-based browsers scrounging the garbage for market share.");
        } else {
            adv.say("I was in front of the bar. The music was still blaring, and those browsers were still digging through the dirt.");
        }

        var extra = 'Otherwise it was a dead end.';
        if (mickeyDone) {
            extra = "I also could've tried talking to the old browsers.";
        }
        adv.say("I could've entered the bar, or going south would've led back to the addon shop. " + extra);
    }, {
        south: 'outsideStore',
        extraCommands: {
            enter: function(cmd) {
                adv.setCurrentRoom('insideBar');
            },
            talk: function() {
                if (knowsWhereAddonIs) {
                    adv.say("I didn't have a reason to talk to the old browser anymore. He had mentioned he hid the addon somewhere near the user script shop.");
                } else if (!mickeyDone) {
                    adv.say("I had better things to do than talk to some old washed-up browsers.");
                } else if (!talkedToHobo) {
                    talkedToHobo = true;
                    adv.say("I walked over to the old browsers and called out.");
                    adv.say("Any of you seen an addon for User-Agent headers?", 'firefox');
                    adv.say("A particularly grubby-looking one nearly tripped as he ran over, beaming at me in a half-crazy way.");
                    adv.say("Yes sir! Yeah sir! I saw it! I took an addon just like that the other day!", 'lynx');
                    adv.say("Where is it now?", 'firefox');
                    adv.say("I hid it, yes I did! But man, is my memory getting a bit corrupted in my old age. I can't remember where!", 'lynx');
                    adv.say("If there was anything I had learned living in this town, it was that the cure for amnesia was a well-placed bribe.");
                } else {
                    adv.say("I walked over to the old browser from before. He eyed me suspiciously, but kept on digging around. Clearly he had decided I wasn't worth his time. Perhaps some money would loosen his lips.");
                }
            },
            bribe: function() {
                if (knowsWhereAddonIs) {
                    adv.say("I had already bribed the browser, I didn't need anything more from him.");
                } else if (!talkedToHobo) {
                    adv.say("Why would I do that? I didn't have any reason to bribe anyone... yet.");
                } else {
                    knowsWhereAddonIs = true;
                    adv.score += 50;
                    adv.say("I threw a few Satoshis on the ground, and the old browser pounced on them before the others could get close.");
                    adv.say("You know, I'm feeling a little better now. I seem to remember leaving the addon somewhere near the user script shop at the webring entrance.", 'lynx');
                    adv.say("I left the old browser to count up his earnings. It felt like it was taking forever to get into this store, but I was getting closer.");
                }
            }
        },
        synonyms: {
            'speak': 'talk',
            'pay': 'bribe'
        },
    });

    var insideBarFirst = true;
    adv.room('insideBar', function() {
        if (insideBarFirst) {
            insideBarFirst = false;
            adv.say("I stepped into the smoke-filled bar. It was stuffed with with cheap suits and cheaper morals, but a browser can't be picky about which parts of the internet he chooses to go to.");
            adv.say("I saw Mickey at a table in the corner. By some act of Berners-Lee, the rest of the bar got some sense into their heads and were leaving him alone.");
        } else {
            adv.say("I was in the bar. Mickey was still his little table, nursing a double of whatever liquid this bar called whiskey.");
        }

        adv.say("There wasn't much else to the bar. I could talk to Mickey, or leave.");
    }, {
        extraCommands: {
            talk: function() {
                if (mickeyDone) {
                    adv.say("I already got the info I needed from Mickey.");
                } else {
                    adv.setCurrentRoom('mickey');
                }
            },
            leave: function() {
                adv.setCurrentRoom('outsideBar');
            },
        },
        synonyms: {
            'speak': 'talk',
            'exit': 'leave'
        },
    });

    var mickeyFirst = true;
    var mickeyDone = false;
    adv.room('mickey', function() {
        if (mickeyFirst) {
            mickeyFirst = false;
            adv.say("I sat down opposite of Mickey. He looked up with the face of a man with no friends. I'd like to say that I was his friend, and that his face brightned up the moment he laid eyes on me, but you and I both know that'd be a hell of a lie.");
            adv.say("Oh, you.", 'mickey');
            adv.say("Yeah, me. How's it going, Mickey?", 'firefox');
            adv.say("Fine. Great. Tremendous. A guy like me couldn't be happier.", 'mickey');
            adv.say("What's got you down?", 'firefox');
            adv.say("Don't even pretend like you care. Whaddya want?", 'mickey');

            if (triedToEnterStore) {
                adv.say("I needed to ask Mickey about getting into that store.");
            } else {
                adv.say("I didn't have much to say to Mickey, so I figured I might as well leave.");
            }
        } else {
            adv.say("I sat back down in front of Mickey.");
            adv.say("You remember what you wanted? If not, leave me alone. I don't need you in my face right now.", 'mickey');
        }
    }, {
        extraCommands: {
            leave: function() {
                adv.say("You know what? I got somewhere to be right now. I'll catch you later, Mickey.", 'firefox');
                adv.say("Yeah, sure... jerk.", 'mickey');
                adv.say("I got up and left Mickey to his pity party.");
                adv.setCurrentRoom('insideBar');
            },
            ask: function(cmd) {
                if (!triedToEnterStore) {
                    adv.say("I didn't really have anything to ask him about at that point.");
                } else {
                    mickeyDone = true;
                    adv.score += 30;
                    adv.say("So, listen. I'm trying to get into that addon store...", 'firefox');
                    adv.say("And you keep getting kicked out because of your User-Agent, right? Yeah, you'll need an addon to spoof your User-Agent to get by. I saw one of those browsers outside going on about an addon he found that sounded like it would do the trick.", 'mickey');
                    adv.say("That's just what I was hoping to hear. Thanks for the help, Mickey.");
                    adv.say("I slipped a few Satoshis on the table for his trouble and left Mickey. Now I was getting somewhere.");
                    adv.setCurrentRoom('insideBar');
                }
            }
        },
        synonyms: {
            'exit': 'leave'
        },
    });

    adv.start();
})();
<commit_msg>Allow "look trash" as valid command for searching the trash.<commit_after>;(function() {
    var adv = new Adventure(document.getElementById('adventure'), 'start');

    function showEndMsg() {
        document.getElementById('endmsglink').href = 'https://wiki.mozilla.org/Webdev/Beer_And_Tell/December2013';
        document.getElementById('endmsg').className = 'show';
    }

    var intro = false;
    var hasAddon = false;
    adv.room('start', function() {
        if (!intro) {
            intro = true;
            adv.say("I can remember it like it was yesterday.");
            adv.say("It was a cold, rainy night. It always is. The story wouldn't be nearly as good if it happened on a sunny afternoon.");
            adv.say("I had known the client for years. She was a good friend; her family took me in when my own kicked me out. And even when I was on the streets, she was still there for me, giving me food and clothes, letting me stay on her couch when I wasn't out on the streets hustling for market share.");
            adv.say("It was a typical story: She was minding her own business, browsing a site someone had linked her to from an email, but she soon noticed some strange-looking ads. They seemed to know more about her than they should've, suggesting things like a present for her brother's birthday. How could they know that it was coming up?");
            adv.say("That's when she looked in her purse and noticed it: someone had slipper her a tracking cookie. And not just any tracking cookie, but an evercookie. The kind that you just can't get rid of.");
            adv.say("I had already given her Ghostery, which handled most other tracking cookies, but this one just wouldn't let go. I knew that we needed something different, and I knew where I could get it.");
            adv.say("I headed down to the Seventh Street webring. Browsers like me weren't always welcome down there; I saw a few 'Best Viewed with Internet Explorer 6' signs. Got a few glares, but I'd been through this dance before. I pulled out Quirks Mode, and people knew to leave me alone.");
        }

        var shop = "There was a closed-down user script shop near the entrance.";
        if (knowsWhereAddonIs && !hasAddon) {
            shop += " I noticed a small trashcan sitting outside the shop.";
        }

        adv.say("I was standing at the entrance to the Seventh Street webring. The dim lights reflected off the puddles in the alley. " + shop);
        adv.say("The alley continued north, deeper into the webring. South led back out the webring, but I still had business to take care of. Leaving then would've been nothing but trouble.");
    }, {
        north: 'outsideStore',
        south: 'utterFailure',
        extraCommands: {
            search: function(cmd) {
                if (cmd.indexOf('trash') === -1) {
                    adv.say("I couldn't find anything there. Maybe somewhere else?");
                } else if (hasAddon) {
                    adv.say("I searched the trash again, but couldn't find anything else useful");
                } else if (knowsWhereAddonIs) {
                    hasAddon = true;
                    adv.score += 100;
                    adv.say("I was no stranger to digging through the trash, and soon enough I found a beat-up looking addon. Just like the old browser said, it was a User-Agent spoofer. I configured it to mask me as Internet Explorer 6 and installed it.");
                } else {
                    adv.say("I didn't know what I was searching for, and couldn't find anything useful anyway.");
                }
            },

            look: function(cmd) {
                if (cmd.indexOf('trash') !== -1 && (knowsWhereAddonIs || hasAddon)) {
                    adv.currentRoom.extraCommands.search(cmd);
                } else {
                    adv.look();
                }
            }
        },
        synonyms: {
            'examine': 'search',
            'look in': 'search',
            'check': 'search'
        },
    });

    adv.room('utterFailure', function() {
        adv.say("You think I'm the kind of guy who high-tails it when going gets tough? Buzz off! Get outta my face, you lowlife scum!");
        adv.endGame(true);
    });

    var outsideStoreFirstVisit = true;
    var triedToEnterStore = false;
    adv.room('outsideStore', function() {
        var extra = '';
        if (outsideStoreFirstVisit) {
            outsideStoreFirstVisit = false;
            adv.say("I moved deeper into the alleyway. The stench of <FONT>s wafted through the air. This place was bad news, but I'd seen worse.");
            adv.say("I stood in front of a badly-lit addon shop. This was where I needed to be; I had heard rumors the guy who ran this shop could find any addon. Obviously, this kind of service didn't come cheap.");
        } else {
            extra = "I was back outside the addon shop. ";
        }

        adv.say(extra + "I could've tried to enter the shop. North led further into the webring, while south led back to the webring entrance.");
    }, {
        south: 'start',
        north: 'outsideBar',
        extraCommands: {
            enter: function(cmd) {
                if (hasAddon) {
                    adv.say("This time, when I tried the door, it opened immediately. Finally, I could move on!");
                    adv.say("I walked into the store. The walls will filled with shelves stuffed with addons for almost anything you could imagine, from showing the prices for an item from other sites for comparison, to storing tabs in a tree-structure, to changing the menu icon into a hamburger.");
                    adv.say("As I headed to the back of the store, I heard an old man's voice call out to me. I saw a small man standing behind a counter waving to me. As I approached, I realized this was the merchant I had been told about. He was the one who could help me find an addon for my client.");
                    adv.say("So you're the one looking for an addon to get rid of an evercookie, eh?", 'potch');
                    adv.say("How do you know about that?", 'firefox');
                    adv.say("Young man, it's my business to know these things. How could I find an addon like this if I couldn't even find out a bit of news about you?", 'potch');
                    adv.say("But that doesn't matter. Seeing that you were able to get past my door, I'm willing to help you. You've proved to be a resourceful little browser, and I'm prepared to give you information on where to aquire this addon. In return, I expect you to do something for me.", 'potch');
                    adv.say("And what do you need me to do?", 'firefox');
                    adv.say("Hah! So eager! You need to relax, young man. What I want from you will be made clear later. For now, you should track down this addon for your client.", 'potch');
                    adv.prompt("He handed me a small business card and instructed me to visit the URL on the card to find what I was looking for. However, when I sent a request to the page, all I got back was a 302 redirect and a very odd response body that said...", function() {
                        showEndMsg();
                    });
                } else {
                    var firstBlock = !triedToEnterStore;

                    triedToEnterStore = true;
                    adv.score += 10;
                    adv.say("I tried to open the front door, but it wouldn't budge. When I pulled on the knob, a small message popped up in the window:");
                    adv.say("'We only support Internet Explorer 6'");
                    adv.say("It looked like the shop was actively blocking any User-Agent that didn't match IE6. I realized I'd need to fool the shop somehow before I could get in.");

                    if (firstBlock) {
                        adv.say("Lucky for me, I knew a guy who could help me out by the name of Mickey. At that hour he was usually hanging out at a bar down the webring a bit. I figured it'd be a good idea to pay him a visit.");
                    } else {
                        adv.say("I still needed to talk to Mickey about getting past the door.");
                    }
                }
            },
        },
        synonyms: {
            'open': 'enter',
        },
    });

    var outsideBarFirst = true;
    var talkedToHobo = false;
    var knowsWhereAddonIs = false;
    adv.room('outsideBar', function() {
        if (outsideBarFirst) {
            outsideBarFirst = false;
            adv.say("Near the back of the webring was a dingy bar. You could hear the awful auto-playing Midi music from the other end of the webring.");
            adv.say("I knew a guy by the name of Mickey who frequented the bar. Most nights you could find him in some corner, lying his head off about some recent startup or Facebook app he was working on. But for all his faults, he knew this part of town better than anyone.");

            adv.say("Outside the bar there were some old text-based browsers scrounging the garbage for market share.");
        } else {
            adv.say("I was in front of the bar. The music was still blaring, and those browsers were still digging through the dirt.");
        }

        var extra = 'Otherwise it was a dead end.';
        if (mickeyDone) {
            extra = "I also could've tried talking to the old browsers.";
        }
        adv.say("I could've entered the bar, or going south would've led back to the addon shop. " + extra);
    }, {
        south: 'outsideStore',
        extraCommands: {
            enter: function(cmd) {
                adv.setCurrentRoom('insideBar');
            },
            talk: function() {
                if (knowsWhereAddonIs) {
                    adv.say("I didn't have a reason to talk to the old browser anymore. He had mentioned he hid the addon somewhere near the user script shop.");
                } else if (!mickeyDone) {
                    adv.say("I had better things to do than talk to some old washed-up browsers.");
                } else if (!talkedToHobo) {
                    talkedToHobo = true;
                    adv.say("I walked over to the old browsers and called out.");
                    adv.say("Any of you seen an addon for User-Agent headers?", 'firefox');
                    adv.say("A particularly grubby-looking one nearly tripped as he ran over, beaming at me in a half-crazy way.");
                    adv.say("Yes sir! Yeah sir! I saw it! I took an addon just like that the other day!", 'lynx');
                    adv.say("Where is it now?", 'firefox');
                    adv.say("I hid it, yes I did! But man, is my memory getting a bit corrupted in my old age. I can't remember where!", 'lynx');
                    adv.say("If there was anything I had learned living in this town, it was that the cure for amnesia was a well-placed bribe.");
                } else {
                    adv.say("I walked over to the old browser from before. He eyed me suspiciously, but kept on digging around. Clearly he had decided I wasn't worth his time. Perhaps some money would loosen his lips.");
                }
            },
            bribe: function() {
                if (knowsWhereAddonIs) {
                    adv.say("I had already bribed the browser, I didn't need anything more from him.");
                } else if (!talkedToHobo) {
                    adv.say("Why would I do that? I didn't have any reason to bribe anyone... yet.");
                } else {
                    knowsWhereAddonIs = true;
                    adv.score += 50;
                    adv.say("I threw a few Satoshis on the ground, and the old browser pounced on them before the others could get close.");
                    adv.say("You know, I'm feeling a little better now. I seem to remember leaving the addon somewhere near the user script shop at the webring entrance.", 'lynx');
                    adv.say("I left the old browser to count up his earnings. It felt like it was taking forever to get into this store, but I was getting closer.");
                }
            }
        },
        synonyms: {
            'speak': 'talk',
            'pay': 'bribe'
        },
    });

    var insideBarFirst = true;
    adv.room('insideBar', function() {
        if (insideBarFirst) {
            insideBarFirst = false;
            adv.say("I stepped into the smoke-filled bar. It was stuffed with with cheap suits and cheaper morals, but a browser can't be picky about which parts of the internet he chooses to go to.");
            adv.say("I saw Mickey at a table in the corner. By some act of Berners-Lee, the rest of the bar got some sense into their heads and were leaving him alone.");
        } else {
            adv.say("I was in the bar. Mickey was still his little table, nursing a double of whatever liquid this bar called whiskey.");
        }

        adv.say("There wasn't much else to the bar. I could talk to Mickey, or leave.");
    }, {
        extraCommands: {
            talk: function() {
                if (mickeyDone) {
                    adv.say("I already got the info I needed from Mickey.");
                } else {
                    adv.setCurrentRoom('mickey');
                }
            },
            leave: function() {
                adv.setCurrentRoom('outsideBar');
            },
        },
        synonyms: {
            'speak': 'talk',
            'exit': 'leave'
        },
    });

    var mickeyFirst = true;
    var mickeyDone = false;
    adv.room('mickey', function() {
        if (mickeyFirst) {
            mickeyFirst = false;
            adv.say("I sat down opposite of Mickey. He looked up with the face of a man with no friends. I'd like to say that I was his friend, and that his face brightned up the moment he laid eyes on me, but you and I both know that'd be a hell of a lie.");
            adv.say("Oh, you.", 'mickey');
            adv.say("Yeah, me. How's it going, Mickey?", 'firefox');
            adv.say("Fine. Great. Tremendous. A guy like me couldn't be happier.", 'mickey');
            adv.say("What's got you down?", 'firefox');
            adv.say("Don't even pretend like you care. Whaddya want?", 'mickey');

            if (triedToEnterStore) {
                adv.say("I needed to ask Mickey about getting into that store.");
            } else {
                adv.say("I didn't have much to say to Mickey, so I figured I might as well leave.");
            }
        } else {
            adv.say("I sat back down in front of Mickey.");
            adv.say("You remember what you wanted? If not, leave me alone. I don't need you in my face right now.", 'mickey');
        }
    }, {
        extraCommands: {
            leave: function() {
                adv.say("You know what? I got somewhere to be right now. I'll catch you later, Mickey.", 'firefox');
                adv.say("Yeah, sure... jerk.", 'mickey');
                adv.say("I got up and left Mickey to his pity party.");
                adv.setCurrentRoom('insideBar');
            },
            ask: function(cmd) {
                if (!triedToEnterStore) {
                    adv.say("I didn't really have anything to ask him about at that point.");
                } else {
                    mickeyDone = true;
                    adv.score += 30;
                    adv.say("So, listen. I'm trying to get into that addon store...", 'firefox');
                    adv.say("And you keep getting kicked out because of your User-Agent, right? Yeah, you'll need an addon to spoof your User-Agent to get by. I saw one of those browsers outside going on about an addon he found that sounded like it would do the trick.", 'mickey');
                    adv.say("That's just what I was hoping to hear. Thanks for the help, Mickey.");
                    adv.say("I slipped a few Satoshis on the table for his trouble and left Mickey. Now I was getting somewhere.");
                    adv.setCurrentRoom('insideBar');
                }
            }
        },
        synonyms: {
            'exit': 'leave'
        },
    });

    adv.start();
})();
<|endoftext|>


<commit_before>import NodeKinvey from 'kinvey-node-sdk';
import { CacheRack } from './rack';
import Popup from './popup';
import assign from 'lodash/assign';

export default class Kinvey extends NodeKinvey {
  static init(options = {}) {
    options = assign({
      cacheRack: new CacheRack(),
      popupClass: Popup
    }, options);
    return super.init(options);
  }
}
<commit_msg>Use Device module for deviceClass<commit_after>import NodeKinvey from 'kinvey-node-sdk';
import { CacheRack } from './rack';
import Popup from './popup';
import Device from './device';
import assign from 'lodash/assign';

export default class Kinvey extends NodeKinvey {
  static init(options = {}) {
    options = assign({
      cacheRack: new CacheRack(),
      deviceClass: Device,
      popupClass: Popup
    }, options);
    return super.init(options);
  }
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

'use strict';

const path = require('path');
const childProcess = require('child_process');

function findChangedFiles(cwd) {
  return new Promise((resolve, reject) => {
    const args = ['status', '-amn'];
    const child = childProcess.spawn('hg', args, {cwd});

    let stdout = '';
    let stderr = '';
    child.stdout.on('data', data => stdout += data);
    child.stderr.on('data', data => stderr += data);
    child.on('close', code => {
      if (code === 0) {
        stdout = stdout.trim();
        if (stdout === '') {
          resolve([]);
        } else {
          resolve(stdout.split('\n').map(
            changedPath => path.resolve(cwd, changedPath)
          ));
        }
      } else {
        reject(code + ': ' + stderr);
      }
    });
  });
}

function isHGRepository(cwd) {
  return new Promise(resolve => {
    try {
      let stdout = '';
      const child = childProcess.spawn('hg', ['root'], {cwd});
      child.stdout.on('data', data => stdout += data);
      child.on('error', () => resolve(null));
      child.on('close', code => resolve(code === 0 ? stdout.trim() : null));
    } catch (e) {
      resolve(null);
    }
  });
}

exports.isHGRepository = isHGRepository;
exports.findChangedFiles = findChangedFiles;
<commit_msg>Update internal runner CLI messages + hg integration<commit_after>/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

'use strict';

const path = require('path');
const childProcess = require('child_process');

function findChangedFiles(cwd, options) {
  return new Promise((resolve, reject) => {
    const args = ['status', '--root-relative', '-amn'];
    if (options && options.withAncestor) {
      args.push('--rev', 'ancestor(.^)');
    }
    const child = childProcess.spawn('hg', args, {cwd});

    let stdout = '';
    let stderr = '';
    child.stdout.on('data', data => stdout += data);
    child.stderr.on('data', data => stderr += data);
    child.on('close', code => {
      if (code === 0) {
        stdout = stdout.trim();
        if (stdout === '') {
          resolve([]);
        } else {
          resolve(stdout.split('\n').map(
            changedPath => path.resolve(cwd, changedPath)
          ));
        }
      } else {
        reject(code + ': ' + stderr);
      }
    });
  });
}

function isHGRepository(cwd) {
  return new Promise(resolve => {
    try {
      let stdout = '';
      const child = childProcess.spawn('hg', ['root'], {cwd});
      child.stdout.on('data', data => stdout += data);
      child.on('error', () => resolve(null));
      child.on('close', code => resolve(code === 0 ? stdout.trim() : null));
    } catch (e) {
      resolve(null);
    }
  });
}

exports.isHGRepository = isHGRepository;
exports.findChangedFiles = findChangedFiles;
<|endoftext|>


<commit_before>require("babel-register")()
var compile_text = require("./compiler").compile_text;

module.exports = function(text) {
    this.cacheable();
    return compile_text(text);
}
<commit_msg>Correct propagation of options in webpack loader<commit_after>require("babel-register")()
var compile_text = require("./compiler").compile_text;

module.exports = function(text) {
    this.cacheable();
    return compile_text(text, this.options.khufu || {});
}
<|endoftext|>


<commit_before>import { gltfImageProcessor } from "./image_processor";

class gltfLoader
{
    static async load(gltf, appendix = undefined)
    {
        const buffers = gltfLoader.getBuffers(appendix);
        const additionalFiles = gltfLoader.getAdditionalFiles(appendix);

        const buffersPromise = gltfLoader.loadBuffers(gltf, buffers, additionalFiles);
        const imagesPromise = gltfLoader.loadImages(gltf, additionalFiles)
            .then(() => gltfLoader.processImages(gltf));

        return await Promise.all([buffersPromise, imagesPromise])
            .then(() => gltf.initGl());
    }

    static unload(gltf)
    {
        for (let image of gltf.images)
        {
            image.image = undefined;
        }
        gltf.images = [];

        for (let texture of gltf.textures)
        {
            texture.destroy();
        }
        gltf.textures = [];

        for (let accessor of gltf.accessors)
        {
            accessor.destroy();
        }
        gltf.accessors = [];
    }

    static getBuffers(appendix)
    {
        return gltfLoader.getTypedAppendix(appendix, ArrayBuffer);
    }

    static getAdditionalFiles(appendix)
    {
        return gltfLoader.getTypedAppendix(appendix, File);
    }

    static getTypedAppendix(appendix, Type)
    {
        if (appendix && appendix.length > 0)
        {
            if (appendix[0] instanceof Type)
            {
                return appendix;
            }
        }
    }

    static loadBuffers(gltf, buffers, additionalFiles)
    {
        const promises = [];
        if (buffers)
        {
            const count = Math.min(buffers.length, gltf.buffers.length);
            for (let i = 0; i < count; ++i)
            {
                gltf.buffers[i].buffer = buffers[i];
            }
        }
        else
        {
            for (const buffer of gltf.buffers)
            {
                promises.push(buffer.load(gltf, additionalFiles));
            }
        }
        return Promise.all(promises);
    }

    static loadImages(gltf, additionalFiles)
    {
        const imagePromises = [];
        for (let image of gltf.images)
        {
            imagePromises.push(image.load(gltf, additionalFiles));
        }
        return Promise.all(imagePromises);
    }

    static processImages(gltf)
    {
        const imageProcessor = new gltfImageProcessor();
        imageProcessor.processImages(gltf);
    }
}

export { gltfLoader };
<commit_msg>fix ktx from binary buffers<commit_after>import { gltfImageProcessor } from "./image_processor";

class gltfLoader
{
    static async load(gltf, appendix = undefined)
    {
        const buffers = gltfLoader.getBuffers(appendix);
        const additionalFiles = gltfLoader.getAdditionalFiles(appendix);

        const buffersPromise = gltfLoader.loadBuffers(gltf, buffers, additionalFiles);
        await buffersPromise;
        const imagesPromise = gltfLoader.loadImages(gltf, additionalFiles)
            .then(() => gltfLoader.processImages(gltf));

        return await Promise.all([buffersPromise, imagesPromise])
            .then(() => gltf.initGl());
    }

    static unload(gltf)
    {
        for (let image of gltf.images)
        {
            image.image = undefined;
        }
        gltf.images = [];

        for (let texture of gltf.textures)
        {
            texture.destroy();
        }
        gltf.textures = [];

        for (let accessor of gltf.accessors)
        {
            accessor.destroy();
        }
        gltf.accessors = [];
    }

    static getBuffers(appendix)
    {
        return gltfLoader.getTypedAppendix(appendix, ArrayBuffer);
    }

    static getAdditionalFiles(appendix)
    {
        return gltfLoader.getTypedAppendix(appendix, File);
    }

    static getTypedAppendix(appendix, Type)
    {
        if (appendix && appendix.length > 0)
        {
            if (appendix[0] instanceof Type)
            {
                return appendix;
            }
        }
    }

    static loadBuffers(gltf, buffers, additionalFiles)
    {
        const promises = [];
        if (buffers)
        {
            const count = Math.min(buffers.length, gltf.buffers.length);
            for (let i = 0; i < count; ++i)
            {
                gltf.buffers[i].buffer = buffers[i];
            }
        }
        else
        {
            for (const buffer of gltf.buffers)
            {
                promises.push(buffer.load(gltf, additionalFiles));
            }
        }
        return Promise.all(promises);
    }

    static loadImages(gltf, additionalFiles)
    {
        const imagePromises = [];
        for (let image of gltf.images)
        {
            imagePromises.push(image.load(gltf, additionalFiles));
        }
        return Promise.all(imagePromises);
    }

    static processImages(gltf)
    {
        const imageProcessor = new gltfImageProcessor();
        imageProcessor.processImages(gltf);
    }
}

export { gltfLoader };
<|endoftext|>


<commit_before>import Transformer from './transformer.js';
import Path from './path.js';

// import export in strings cause error
// backtick in template strings or regex could possibly causes issues

export default {

	data: {},
	type: 'esm',

	async setup (options) {
		const self = this;

		options = options || options;
		this.type = options.type || this.type;

		if (options.loads) {
			return Promise.all(options.loads.map(function (load) {
				return self.load(load);
			}));
		}

	},

	async load () {
		let url, type;

		if (typeof arguments[0] === 'object') {
			url = arguments[0]['url'];
			type = arguments[0]['type'];
		} else {
			url = arguments[0];
			type = arguments[1] || this.type;
		}

		if (!url) {
			throw new Error('Oxe.loader.load - url argument required');
		}

		url = Path.normalize(url);
		// needed for the cli
		// url = Path.join(Path.base, url);

		if (url in this.data) {
			return this.data[url];
		}

		const data = await window.fetch(url);

		if (data.status == 404) {
			throw new Error('Oxe.loader.load - not found ' + url);
		}

		if (data.status < 200 || data.status > 300 && data.status != 304) {
			throw new Error(data.statusText);
		}

		let code;

		code = await data.text();

		if (type === 'es' || type === 'est') {
			code = Transformer.template(code);
		}

		if (type === 'es' || type === 'esm') {
			code = Transformer.module(code, url);
		}

		code = new Function('window', 'document', '$LOADER', code);

		return this.data[url] = code(window, window.document, this);
	}

};
<commit_msg>removed comment<commit_after>import Transformer from './transformer.js';
import Path from './path.js';

// import export in strings cause error
// backtick in template strings or regex could possibly causes issues

export default {

	data: {},
	type: 'esm',

	async setup (options) {
		const self = this;

		options = options || options;
		this.type = options.type || this.type;

		if (options.loads) {
			return Promise.all(options.loads.map(function (load) {
				return self.load(load);
			}));
		}

	},

	async load () {
		let url, type;

		if (typeof arguments[0] === 'object') {
			url = arguments[0]['url'];
			type = arguments[0]['type'];
		} else {
			url = arguments[0];
			type = arguments[1] || this.type;
		}

		if (!url) {
			throw new Error('Oxe.loader.load - url argument required');
		}

		url = Path.normalize(url);

		if (url in this.data) {
			return this.data[url];
		}

		const data = await window.fetch(url);

		if (data.status == 404) {
			throw new Error('Oxe.loader.load - not found ' + url);
		}

		if (data.status < 200 || data.status > 300 && data.status != 304) {
			throw new Error(data.statusText);
		}

		let code;

		code = await data.text();

		if (type === 'es' || type === 'est') {
			code = Transformer.template(code);
		}

		if (type === 'es' || type === 'esm') {
			code = Transformer.module(code, url);
		}

		code = new Function('window', 'document', '$LOADER', code);

		return this.data[url] = code(window, window.document, this);
	}

};
<|endoftext|>


<commit_before>(function (n, c) {
  if (c[n] === void 0) {
    c[n] = function () {
      c[n].clients.push(this)
      this._init = [Array.prototype.slice.call(arguments)]
    }
    c[n].clients = []

    var action = function (method) {
      return function () {
        this['_' + method] = this['_' + method] || []
        this['_' + method].push(Array.prototype.slice.call(arguments))
        return this
      }
    }

    var methods = ['addRecord', 'set', 'trackEvent', 'trackPageview', 'ready']
    for (var i = 0; i < methods.length; i++) {
      var method = methods[i]
      c[n].prototype[method] = action(method)
    }

    var s = document.createElement('script')
    s.type = 'text/javascript'
    s.async = !0
    s.src = (document.location.protocol === 'https:' ? 'https:' : 'http:') + '@URL'

    var t = document.getElementsByTagName('script')[0]
    t.parentNode.insertBefore(s, t)
  }
})('Treasure', this)
<commit_msg>Use sed to set the loader global identifier<commit_after>(function (n, c) {
  if (c[n] === void 0) {
    c[n] = function () {
      c[n].clients.push(this)
      this._init = [Array.prototype.slice.call(arguments)]
    }
    c[n].clients = []

    var action = function (method) {
      return function () {
        this['_' + method] = this['_' + method] || []
        this['_' + method].push(Array.prototype.slice.call(arguments))
        return this
      }
    }

    var methods = ['addRecord', 'set', 'trackEvent', 'trackPageview', 'ready']
    for (var i = 0; i < methods.length; i++) {
      var method = methods[i]
      c[n].prototype[method] = action(method)
    }

    var s = document.createElement('script')
    s.type = 'text/javascript'
    s.async = !0
    s.src = (document.location.protocol === 'https:' ? 'https:' : 'http:') + '@URL'

    var t = document.getElementsByTagName('script')[0]
    t.parentNode.insertBefore(s, t)
  }
})('@GLOBAL', this)
<|endoftext|>


<commit_before>/* bower component loader for the browser
 ________________________________________________________________________________________
 *
 * Easly Import your components or libraries installed via bower to your project.
 *
 * @license MIT
 * @author  [Tindo Ngoufo Arsel](mailto:devtnga@gmail.com)
*/

//manage possible conflict with loader namespace definition.
if ( typeof bower !== "undefined" ) {

    console.warn("Seem like `bower` namespace is use for another purpose. Taking risk of an overwrite ...") ;
    window.bower = bower = {} ;
    console.warn("Forcing `bower` namespace initialization ... done.") ;

} else {

    window.bower = {} ;
}

/* importing package is an interresting hack when we have to avoid duplicate import and manage dependencies.
 * the method here is to have a registry where we will add package's configuration in particular order (function of dependency or not).
 * package's configuration is an object build from `bower.json` assciated file.
 * dependencies will always be imported before package of which depends ; this influences how order is done in packages's configuration registry.
 * package have to have a unique occurrence on the registry ; this assure that we will not have duplicate component's import.
*/

bower.dir = "../.." ;      //bower base directory
bower.pkgCount = 0 ;       //number of package that have been loaded
bower.loadingCount = 0 ;   //have many package are in loading process
bower.total = 0 ;          //total number of packages that must to be loaded
bower.packagesTree = [] ;   //packages's configuration registry

/**
 * get the text reponse throught an ajax request from a given path
 * @param   {string}   path     path where to get file's content
 * @param   {boolean}  isAsync  enable request asynchrone or not
 * @param   {function} callback the function to execute after the end of request process. take the returned object as argument
 * @returns {object}   content the answer informations with this properties {error: boolean, status: number, statusText: string, text: string}
 */
bower.xhrGet = function (path, isAsync, callback) {

    if (typeof path !== "string" && !(path instanceof String)) {

        console.error("bowerder: path must be give as a string") ;
        return null ;
    }

    isAsync = (typeof isAsync === "boolean" || isAsync instanceof Boolean) ? isAsync : true ;
    callback = (typeof callback === "function" || callback instanceof Function) ? callback : undefined ;

    var xhr = undefined ;

    if (window.XMLHttpRequest) {

        xhr = new XMLHttpRequest(); //For Chrome, Firefox, Opera and others...

        if (xhr.overrideMimeType)
            xhr.overrideMimeType("text/xml"); //Avoid Safari’s bug
    }
    else if (window.ActiveXObject) {
        //For Internet Explorer
        try {
            xhr = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e1) {
            try {
                xhr = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e2) {
                console.warn( e1.message );
                console.warn( e2.message );
            }
        }
    }

    if (!(xhr instanceof Object)) {

        console.error("bowerder: Can’t init Ajax functionalities. Maybe it’s your browser version ?") ;
        return null ;
    }

    //on soumet les champs de connexion à la page de traitement approprié pour vérification
    xhr.open('GET', path, true) ;
    //xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") ;
    // Si la requêtte s'est exécutée sans erreur on recupère le resultat du traitement
    xhr.send() ;

    xhr.onreadystatechange = function() {

        var response = {} ;
        response.error = false ;

        if(xhr.readyState == 4 && xhr.status == 200) {

            response.status = xhr.status ;
            response.text = xhr.responseText ;

            if (callback) callback( response ) ;

            return response ;
        }
        else if ( xhr.status != 200) {

            response.status = xhr.status ;
            response.statusText = xhr.statusText ;
            response.error = true ;
            console.error("bowerder: Ajax request error (status: "+ xhr.status +"), try to check your connection. ") ;

            return response ;
        }
    }
} ;

/**
 * helpfull to determine if a package is in the packages's configuration registry
 * @param   {string} pkgName the name of the package
 * @returns {number} index of the first occurrence of the given package. -1 if it's isn't in the registry.
 */
bower.packageIndex = function (pkgName) {

    if (typeof pkgName !== "string" && !(pkgName instanceof String)) {

        console.error("bowerder:packageIndex: argument must be a string" );
    }
    else {

        for (i in bower.packagesTree) {

            if (bower.packagesTree[i].name === pkgName) return i ;
        }
    }

    return -1 ;
} ;

bower.parseTagType = function (targetFile) {

    if (typeof targetFile !== "string" && !(targetFile instanceof String)) {

        console.error("bowerder:parseTagType: argument must be a string" );
    }

    var tag = {name: "unknow", type: "unknow"} ;

    if (/\.js$/.test( targetFile )) { //it's a js like file

        tag.name = "script" ;
        tag.type = "text/javascript" ;
    }
    if (/\.css$/.test( targetFile ) || /\.scss$/.test( targetFile ) || /\.sass$/.test( targetFile ) || /\.less$/.test( targetFile )) { //it's a css like

        tag.name = "link" ;
        tag.type = "text/css" ;

        if (/\.css$/.test( targetFile )) tag.rel = "stylesheet" ;
        if (/\.scss$/.test( targetFile )) tag.rel = "stylesheet/scss" ;
        if (/\.sass$/.test( targetFile )) tag.rel = "stylesheet/sass" ;
        if (/\.less$/.test( targetFile )) tag.rel = "stylesheet/less" ;
    }

    return tag ;
} ;

bower.addPackage = function (pkgName, pkgCaller) {

    if (typeof pkgName !== "string" && !(pkgName instanceof String)) {

        console.error("bowerder:addPackage: argument must be a string" );
        return null ;
    }
    if (pkgCaller && (typeof pkgCaller !== "string") && !(pkgCaller instanceof String)) console.warn("bowerder:addPackage: argument must be a string") ;

    var isAlreadyOk = false ;

    /* check if package to load is already present in the registry.
     * if it's a dependency, check if it's present in the registry before package of which depends.
     * if so, nothing will be done, else the adding operation to the registry will be process.
    */
    for (i in bower.packagesTree.length) {

        if (bower.packagesTree[i].name === pkgName ) {

            isAlreadyOk = true ;

            if (pkgCaller && (bower.packageIndex( pkgCaller ) != -1) ) {
                /* major browsers load and execute script included by another script asynchronously.
                 * the problem here is that, package which have dependencies have to be execute after them.
                 * therefore, for these package, it's primordial to load them synchronously.
                */
                //bower.packagesTree[i].browser.async = false ;
                bower.packagesTree[ bower.packageIndex( pkgCaller ) ].browser.async = false ;

                if (bower.packageIndex( pkgCaller ) < i) isAlreadyOk = false ;
            }

            break ;
        }
    }

    if (!isAlreadyOk) { //process the adding operation to the registry.

        bower.loadingCount++ ;

        bower.xhrGet( bower.dir +"/"+ pkgName +"/bower.json", true, function (reponse) {

            if (reponse.error) {

                bower.loadingCount-- ;
                console.error("bowerder:addPackage: unable to load `"+ pkgName +"` component." );

                return null ;
            }

            var pkgConfig = JSON.parse( reponse.text ) ;

            if (pkgConfig instanceof Object) {

                delete pkgConfig['ignore'] ;
                delete pkgConfig['keywords'] ;
                delete pkgConfig['moduleType'] ;
                delete pkgConfig['resolutions'] ;

                if (!(pkgConfig.browser instanceof Object)) pkgConfig.browser = {} ;
                //by default, load and execute script asynchronously
                pkgConfig.browser.async = true ;

                /* if `pkgCaller` is set, then current loading package adress by `pkgName` is a dependency.
                 * therefore, it have to be added before the `pkgCaller` in the packages's configuration registry.
                 * else it's a just a package to add in the considered registry.
                */
                if (pkgCaller) {

                    //mark package to be synchronously loaded and executed
                    //pkgConfig.browser.async = false ;
                    bower.packagesTree[ bower.packageIndex( pkgCaller ) ].browser.async = false ;

                    if (bower.packageIndex( pkgCaller ) != -1) {

                        bower.packagesTree.splice( bower.packageIndex( pkgCaller ), 0, pkgConfig) ;
                    }
                }
                else {

                    bower.packagesTree.push( pkgConfig ) ;
                }

                //if the current loading package have dependencies, then also process their loading
                if (pkgConfig["dependencies"]) {

                    var pkgDeps = Object.getOwnPropertyNames( pkgConfig["dependencies"] );

                    pkgDeps.forEach( function (name) {

                        bower.addPackage( name, pkgConfig["name"]) ;
                    }) ;
                }
            }
            else {

                console.warn("bowerder:addPackage: unable to load `"+ pkgName +"` component." );
            }

            bower.loadingCount-- ;

            //when all the loading package process are finished, process their importation on the DOM.
            if (bower.loadingCount === 0) {

                //be sure to have unique package occurence in package's tree
                for (var i=0; i < bower.packagesTree.length; i++) {

                    for (var j=i+1; j < bower.packagesTree.length; j++) {

                        if (bower.packagesTree[i].name === bower.packagesTree[j].name) {

                            bower.packagesTree.splice( j, 1) ;
                            j-- ;
                        }
                    }
                }

                var pkgScriptTags = [] ,
                    pkgLinkTags = [] ,
                    pkgLoaderTags = [] ,
                    loaderTag = undefined ,
                    getTag = undefined ; //supported tag

                bower.packagesTree.forEach( function (pkg) {

                    if (typeof pkg.main === "string") pkg.main = [pkg.main] ;

                    for (index in pkg.main) {

                        getTag = bower.parseTagType( pkg.main[index] ) ;

                        if (getTag.name === "script") {

                            loaderTag = document.createElement("script") ;
                            loaderTag.type = getTag.type ;
                            loaderTag.async = pkg.browser.async ;
                            loaderTag.src = bower.dir +"/"+ pkg.name +"/"+ pkg.main[index] ;

                            pkgScriptTags.push( loaderTag ) ;
                        }
                        if (getTag.name === "link") {

                            loaderTag = document.createElement("link") ;
                            loaderTag.rel = getTag.rel ;
                            loaderTag.type = getTag.type ;
                            loaderTag.href = bower.dir +"/"+ pkg.name +"/"+ pkg.main[index] ;

                            pkgLinkTags.push( loaderTag ) ;
                        }
                        if (getTag.name === "unknow") {

                            //console.warn("bowerder: unable to load unsupported file: "+ bower.dir +"/"+ pkg.name +"/"+ pkg.main[index]) ;
                        }
                    }

                    pkgLoaderTags = pkgLinkTags.concat( pkgScriptTags ) ;

                    pkgLoaderTags.forEach( function (importTag) {

                        document.head.appendChild( importTag ) ;
                    }) ;
                }) ;

                console.log(bower.packagesTree) ;
            }
        }) ;
    }
};

bower.import = function (pkgName) {

    if (typeof pkgName !== "string" && !(pkgName instanceof String)) {

        console.error("bowerder:import: argument must be a string" );
        return null ;
    }

    bower.addPackage( pkgName ) ;
};<commit_msg>fix and improvements<commit_after>/* bower component loader for the browser
 ________________________________________________________________________________________
 *
 * Easly Import your components or libraries installed via bower to your project.
 *
 * @license MIT
 * @author  [Tindo Ngoufo Arsel](mailto:devtnga@gmail.com)
*/

//manage possible conflict with loader namespace definition.
if ( typeof bower !== "undefined" ) {

    console.warn("Seem like `bower` namespace is use for another purpose. Taking risk of an overwrite ...") ;
    window.bower = bower = {} ;
    console.warn("Forcing `bower` namespace initialization ... done.") ;

} else {

    window.bower = {} ;
}

/* importing package is an interresting hack when we have to avoid duplicate import and manage dependencies.
 * the method here is to have a registry where we will add package's configuration in particular order (function of dependency or not).
 * package's configuration is an object build from `bower.json` assciated file.
 * dependencies will always be imported before package of which depends ; this influences how order is done in packages's configuration registry.
 * package have to have a unique occurrence on the registry ; this assure that we will not have duplicate component's import.
*/

bower.dir = "../.." ;      //bower base directory
bower.pkgCount = 0 ;       //number of package that have been loaded
bower.loadingCount = 0 ;   //have many package are in loading process
bower.total = 0 ;          //total number of packages that must to be loaded
bower.packagesTree = [] ;   //packages's configuration registry

/**
 * get the text reponse throught an ajax request from a given path
 * @param   {string}   path     path where to get file's content
 * @param   {boolean}  isAsync  enable request asynchrone or not
 * @param   {function} callback the function to execute after the end of request process. take the returned object as argument
 * @returns {object}   content the answer informations with this properties {error: boolean, status: number, statusText: string, text: string}
 */
bower.xhrGet = function (path, isAsync, callback) {

    if (typeof path !== "string" && !(path instanceof String)) {

        console.error("bowerder: path must be give as a string") ;
        return null ;
    }

    isAsync = (typeof isAsync === "boolean" || isAsync instanceof Boolean) ? isAsync : true ;
    callback = (typeof callback === "function" || callback instanceof Function) ? callback : undefined ;

    var xhr = undefined ;

    if (window.XMLHttpRequest) {

        xhr = new XMLHttpRequest(); //For Chrome, Firefox, Opera and others...

        if (xhr.overrideMimeType)
            xhr.overrideMimeType("text/xml"); //Avoid Safari’s bug
    }
    else if (window.ActiveXObject) {
        //For Internet Explorer
        try {
            xhr = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e1) {
            try {
                xhr = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e2) {
                console.warn( e1.message );
                console.warn( e2.message );
            }
        }
    }

    if (!(xhr instanceof Object)) {

        console.error("bowerder: Can’t init Ajax functionalities. Maybe it’s your browser version ?") ;
        return null ;
    }

    //on soumet les champs de connexion à la page de traitement approprié pour vérification
    xhr.open('GET', path, true) ;
    //xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") ;
    // Si la requêtte s'est exécutée sans erreur on recupère le resultat du traitement
    xhr.send() ;

    xhr.onreadystatechange = function() {

        var response = {} ;
        response.error = false ;

        if(xhr.readyState == 4 && xhr.status == 200) {

            response.status = xhr.status ;
            response.text = xhr.responseText ;

            if (callback) callback( response ) ;

            return response ;
        }
        else if ( xhr.status != 200) {

            response.status = xhr.status ;
            response.statusText = xhr.statusText ;
            response.error = true ;
            console.error("bowerder: Ajax request error (status: "+ xhr.status +"), try to check your connection. ") ;

            return response ;
        }
    }
} ;

/**
 * helpfull to determine if a package is in the packages's configuration registry
 * @param   {string} pkgName the name of the package
 * @returns {number} index of the first occurrence of the given package. -1 if it's isn't in the registry.
 */
bower.packageIndex = function (pkgName) {

    if (typeof pkgName !== "string" && !(pkgName instanceof String)) {

        console.error("bowerder:packageIndex: argument must be a string" );
    }
    else {

        for (i in bower.packagesTree) {

            if (bower.packagesTree[i].name === pkgName) return i ;
        }
    }

    return -1 ;
} ;

/**
 * helpfull to determine which html tag have to be used to import a component in the DOM
 * @param   {string} targetFile component's file to include
 * @returns {object} an object that contains informations about html tag to use
 */
bower.parseTagType = function (targetFile) {

    if (typeof targetFile !== "string" && !(targetFile instanceof String)) {

        console.error("bowerder:parseTagType: argument must be a string" );
    }

    var tag = {name: "unknow", type: "unknow"} ;

    if (/\.js$/.test( targetFile )) { //it's a js like file

        tag.name = "script" ;
        tag.type = "text/javascript" ;
    }
    if (/\.css$/.test( targetFile ) || /\.scss$/.test( targetFile ) || /\.sass$/.test( targetFile ) || /\.less$/.test( targetFile )) { //it's a css like

        tag.name = "link" ;
        tag.type = "text/css" ;

        if (/\.css$/.test( targetFile )) tag.rel = "stylesheet" ;
        if (/\.scss$/.test( targetFile )) tag.rel = "stylesheet/scss" ;
        if (/\.sass$/.test( targetFile )) tag.rel = "stylesheet/sass" ;
        if (/\.less$/.test( targetFile )) tag.rel = "stylesheet/less" ;
    }

    return tag ;
} ;

bower.addPackage = function (pkgName, pkgCaller) {

    if (typeof pkgName !== "string" && !(pkgName instanceof String)) {

        console.error("bowerder:addPackage: argument must be a string" );
        return null ;
    }
    if (pkgCaller && (typeof pkgCaller !== "string") && !(pkgCaller instanceof String)) console.warn("bowerder:addPackage: argument must be a string") ;

    var isAlreadyOk = false ;

    /* check if package to load is already present in the registry.
     * if it's a dependency, check if it's present in the registry before package of which depends.
     * if so, nothing will be done, else the adding operation to the registry will be process.
    */
    for (i in bower.packagesTree) {

        if (bower.packagesTree[i].name === pkgName ) {

            isAlreadyOk = true ;

            if (pkgCaller && (bower.packageIndex( pkgCaller ) != -1) ) {
                /* major browsers load and execute script included by another script asynchronously.
                 * the problem here is that, package which have dependencies have to be execute after them.
                 * therefore, for these package, it's primordial to load them synchronously.
                */
                bower.packagesTree[i].browser.async = false ;
                bower.packagesTree[ bower.packageIndex( pkgCaller ) ].browser.async = false ;

                if (bower.packageIndex( pkgCaller ) < i) isAlreadyOk = false ;
            }

            break ;
        }
    }

    if (!isAlreadyOk) { //process the adding operation to the registry.

        bower.loadingCount++ ;

        bower.xhrGet( bower.dir +"/"+ pkgName +"/bower.json", true, function (reponse) {

            if (reponse.error) {

                bower.loadingCount-- ;
                console.error("bowerder:addPackage: unable to load `"+ pkgName +"` component." );

                return null ;
            }

            var pkgConfig = JSON.parse( reponse.text ) ;

            if (pkgConfig instanceof Object) {

                delete pkgConfig['ignore'] ;
                delete pkgConfig['keywords'] ;
                delete pkgConfig['moduleType'] ;
                delete pkgConfig['resolutions'] ;

                if (!(pkgConfig.browser instanceof Object)) pkgConfig.browser = {} ;
                //by default, load and execute script asynchronously
                pkgConfig.browser.async = true ;

                /* if `pkgCaller` is set, then current loading package adress by `pkgName` is a dependency.
                 * therefore, it have to be added before the `pkgCaller` in the packages's configuration registry.
                 * else it's a just a package to add in the considered registry.
                */
                if (pkgCaller) {

                    //mark package to be synchronously loaded and executed
                    pkgConfig.browser.async = false ;
                    bower.packagesTree[ bower.packageIndex( pkgCaller ) ].browser.async = false ;

                    if (bower.packageIndex( pkgCaller ) != -1) {

                        bower.packagesTree.splice( bower.packageIndex( pkgCaller ), 0, pkgConfig) ;
                    }
                }
                else {

                    bower.packagesTree.push( pkgConfig ) ;
                }

                //if the current loading package have dependencies, then also process their loading
                if (pkgConfig["dependencies"]) {

                    var pkgDeps = Object.getOwnPropertyNames( pkgConfig["dependencies"] );

                    pkgDeps.forEach( function (name) {

                        bower.addPackage( name, pkgConfig["name"]) ;
                    }) ;
                }
            }
            else {

                console.warn("bowerder:addPackage: unable to load `"+ pkgName +"` component." );
            }

            bower.loadingCount-- ;

            //when all the loading package process are finished, process their importation on the DOM.
            if (bower.loadingCount === 0) {

                //be sure to have unique package occurence in package's tree
                for (var i=0; i < bower.packagesTree.length; i++) {

                    for (var j=i+1; j < bower.packagesTree.length; j++) {

                        if (bower.packagesTree[i].name === bower.packagesTree[j].name) {

                            bower.packagesTree.splice( j, 1) ;
                            j-- ;
                        }
                    }
                }

                var pkgScriptTags = [] ,
                    pkgLinkTags = [] ,
                    isAlreadyLoaded = false ,
                    loaderTag = undefined ,
                    getTag = undefined ; //supported tag

                bower.packagesTree.forEach( function (pkg) {

                    if (typeof pkg.main === "string") pkg.main = [pkg.main] ;

                    isAlreadyLoaded = false ;
                    /* before include a loader tag in the DOM, it's primordial to check if the associated file isn't already loaded in.
                     * this assure to have an unique instance of a package in the DOM include by our `bower loader`.
                    */
                    if (document.querySelector) {
                        //efficient : this is for all major browsers and IE>8
                        if (document.head.querySelector('[data-bowerpkg ="'+pkg.name+'"]')) isAlreadyLoaded = true ;
                    }
                    else { //alternative with more hack : this is specialy for IE<=8

                        var domLoaderTags = [].slice.call( document.head.getElementsByTagName("link") ) ;
                            domLoaderTags = domLoaderTags.concat( [].slice.call( document.head.getElementsByTagName("scrpit") ) ) ;
                        for (var j=0; j < domLoaderTags.length; j++) {

                            if (domLoaderTags[j].getAttribute("data-bowerpkg") === pkg.name ) {

                                isAlreadyLoaded = true ;
                                break ;
                            }
                        }
                    }

                    if (!isAlreadyLoaded) {

                        for (index in pkg.main) {

                            getTag = bower.parseTagType( pkg.main[index] ) ;

                            if (getTag.name === "script") {

                                loaderTag = document.createElement("script") ;
                                loaderTag.setAttribute("data-bowerpkg", pkg.name) ;
                                loaderTag.type = getTag.type ;
                                loaderTag.async = pkg.browser.async ;
                                loaderTag.src = bower.dir +"/"+ pkg.name +"/"+ pkg.main[index] ;

                                pkgScriptTags.push( loaderTag ) ;
                            }
                            if (getTag.name === "link") {

                                loaderTag = document.createElement("link") ;
                                loaderTag.setAttribute("data-bowerpkg", pkg.name) ;
                                loaderTag.rel = getTag.rel ;
                                loaderTag.type = getTag.type ;
                                loaderTag.href = bower.dir +"/"+ pkg.name +"/"+ pkg.main[index] ;

                                pkgLinkTags.push( loaderTag ) ;
                            }
                            if (getTag.name === "unknow") {

                                //console.warn("bowerder: unable to load unsupported file: "+ bower.dir +"/"+ pkg.name +"/"+ pkg.main[index]) ;
                            }
                        }
                    }
                }) ;

                pkgLinkTags.concat( pkgScriptTags ).forEach( function(loaderTag) {

                    document.head.appendChild( loaderTag ) ;
                }) ;

                console.log( bower.packagesTree ) ;
            }
        }) ;
    }
};

bower.import = function (pkgName) {

    if (typeof pkgName !== "string" && !(pkgName instanceof String)) {

        console.error("bowerder:import: argument must be a string" );
        return null ;
    }

    bower.addPackage( pkgName ) ;
};<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc type
 * @name angular.Module
 * @module ng
 * @description
 *
 * Interface for configuring angular {@link angular.module modules}.
 */

function setupModuleLoader(window) {

  var $injectorMinErr = minErr('$injector');
  var ngMinErr = minErr('ng');

  function ensure(obj, name, factory) {
    return obj[name] || (obj[name] = factory());
  }

  var angular = ensure(window, 'angular', Object);

  // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
  angular.$$minErr = angular.$$minErr || minErr;

  return ensure(angular, 'module', function() {
    /** @type {Object.<string, angular.Module>} */
    var modules = {};

    /**
     * @ngdoc function
     * @name angular.module
     * @module ng
     * @description
     *
     * The `angular.module` is a global place for creating, registering and retrieving Angular
     * modules.
     * All modules (angular core or 3rd party) that should be available to an application must be
     * registered using this mechanism.
     *
     * When passed two or more arguments, a new module is created.  If passed only one argument, an
     * existing module (the name passed as the first argument to `module`) is retrieved.
     *
     *
     * # Module
     *
     * A module is a collection of services, directives, filters, and configuration information.
     * `angular.module` is used to configure the {@link auto.$injector $injector}.
     *
     * ```js
     * // Create a new module
     * var myModule = angular.module('myModule', []);
     *
     * // register a new service
     * myModule.value('appName', 'MyCoolApp');
     *
     * // configure existing services inside initialization blocks.
     * myModule.config(['$locationProvider', function($locationProvider) {
     *   // Configure existing providers
     *   $locationProvider.hashPrefix('!');
     * }]);
     * ```
     *
     * Then you can create an injector and load your modules like this:
     *
     * ```js
     * var injector = angular.injector(['ng', 'myModule'])
     * ```
     *
     * However it's more likely that you'll just use
     * {@link ng.directive:ngApp ngApp} or
     * {@link angular.bootstrap} to simplify this process for you.
     *
     * @param {!string} name The name of the module to create or retrieve.
     * @param {Array.<string>=} requires If specified then new module is being created. If
     *        unspecified then the module is being retrieved for further configuration.
     * @param {Function} configFn Optional configuration function for the module. Same as
     *        {@link angular.Module#config Module#config()}.
     * @returns {module} new module with the {@link angular.Module} api.
     */
    return function module(name, requires, configFn) {
      var assertNotHasOwnProperty = function(name, context) {
        if (name === 'hasOwnProperty') {
          throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
        }
      };

      assertNotHasOwnProperty(name, 'module');
      if (requires && modules.hasOwnProperty(name)) {
        modules[name] = null;
      }
      return ensure(modules, name, function() {
        if (!requires) {
          throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
             "the module name or forgot to load it. If registering a module ensure that you " +
             "specify the dependencies as the second argument.", name);
        }

        /** @type {!Array.<Array.<*>>} */
        var invokeQueue = [];

        /** @type {!Array.<Function>} */
        var runBlocks = [];

        var config = invokeLater('$injector', 'invoke');

        /** @type {angular.Module} */
        var moduleInstance = {
          // Private state
          _invokeQueue: invokeQueue,
          _runBlocks: runBlocks,

          /**
           * @ngdoc property
           * @name angular.Module#requires
           * @module ng
           * @returns {Array.<string>} List of module names which must be loaded before this module.
           * @description
           * Holds the list of modules which the injector will load before the current module is
           * loaded.
           */
          requires: requires,

          /**
           * @ngdoc property
           * @name angular.Module#name
           * @module ng
           * @returns {string} Name of the module.
           * @description
           */
          name: name,

          /**
           * @ngdoc method
           * @name angular.Module#provider
           * @module ng
           * @param {string} name service name
           * @param {Function} providerType Construction function for creating new instance of the
           *                                service.
           * @description
           * See {@link auto.$provide#provider $provide.provider()}.
           */
          provider: invokeLater('$provide', 'provider'),

          /**
           * @ngdoc method
           * @name angular.Module#factory
           * @module ng
           * @param {string} name service name
           * @param {Function} providerFunction Function for creating new instance of the service.
           * @description
           * See {@link auto.$provide#factory $provide.factory()}.
           */
          factory: invokeLater('$provide', 'factory'),

          /**
           * @ngdoc method
           * @name angular.Module#service
           * @module ng
           * @param {string} name service name
           * @param {Function} constructor A constructor function that will be instantiated.
           * @description
           * See {@link auto.$provide#service $provide.service()}.
           */
          service: invokeLater('$provide', 'service'),

          /**
           * @ngdoc method
           * @name angular.Module#value
           * @module ng
           * @param {string} name service name
           * @param {*} object Service instance object.
           * @description
           * See {@link auto.$provide#value $provide.value()}.
           */
          value: invokeLater('$provide', 'value'),

          /**
           * @ngdoc method
           * @name angular.Module#constant
           * @module ng
           * @param {string} name constant name
           * @param {*} object Constant value.
           * @description
           * Because the constant are fixed, they get applied before other provide methods.
           * See {@link auto.$provide#constant $provide.constant()}.
           */
          constant: invokeLater('$provide', 'constant', 'unshift'),

          /**
           * @ngdoc method
           * @name angular.Module#animation
           * @module ng
           * @param {string} name animation name
           * @param {Function} animationFactory Factory function for creating new instance of an
           *                                    animation.
           * @description
           *
           * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
           *
           *
           * Defines an animation hook that can be later used with
           * {@link ngAnimate.$animate $animate} service and directives that use this service.
           *
           * ```js
           * module.animation('.animation-name', function($inject1, $inject2) {
           *   return {
           *     eventName : function(element, done) {
           *       //code to run the animation
           *       //once complete, then run done()
           *       return function cancellationFunction(element) {
           *         //code to cancel the animation
           *       }
           *     }
           *   }
           * })
           * ```
           *
           * See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and
           * {@link ngAnimate ngAnimate module} for more information.
           */
          animation: invokeLater('$animateProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#filter
           * @module ng
           * @param {string} name Filter name.
           * @param {Function} filterFactory Factory function for creating new instance of filter.
           * @description
           * See {@link ng.$filterProvider#register $filterProvider.register()}.
           */
          filter: invokeLater('$filterProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#controller
           * @module ng
           * @param {string|Object} name Controller name, or an object map of controllers where the
           *    keys are the names and the values are the constructors.
           * @param {Function} constructor Controller constructor function.
           * @description
           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
           */
          controller: invokeLater('$controllerProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#directive
           * @module ng
           * @param {string|Object} name Directive name, or an object map of directives where the
           *    keys are the names and the values are the factories.
           * @param {Function} directiveFactory Factory function for creating new instance of
           * directives.
           * @description
           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
           */
          directive: invokeLater('$compileProvider', 'directive'),

          /**
           * @ngdoc method
           * @name angular.Module#config
           * @module ng
           * @param {Function} configFn Execute this function on module load. Useful for service
           *    configuration.
           * @description
           * Use this method to register work which needs to be performed on module loading.
           */
          config: config,

          /**
           * @ngdoc method
           * @name angular.Module#run
           * @module ng
           * @param {Function} initializationFn Execute this function after injector creation.
           *    Useful for application initialization.
           * @description
           * Use this method to register work which should be performed when the injector is done
           * loading all modules.
           */
          run: function(block) {
            runBlocks.push(block);
            return this;
          }
        };

        if (configFn) {
          config(configFn);
        }

        return  moduleInstance;

        /**
         * @param {string} provider
         * @param {string} method
         * @param {String=} insertMethod
         * @returns {angular.Module}
         */
        function invokeLater(provider, method, insertMethod) {
          return function() {
            invokeQueue[insertMethod || 'push']([provider, method, arguments]);
            return moduleInstance;
          };
        }
      });
    };
  });

}
<commit_msg>style(loader.js): correct JSDoc tags of the params of the function module(name, requires, configFn)<commit_after>'use strict';

/**
 * @ngdoc type
 * @name angular.Module
 * @module ng
 * @description
 *
 * Interface for configuring angular {@link angular.module modules}.
 */

function setupModuleLoader(window) {

  var $injectorMinErr = minErr('$injector');
  var ngMinErr = minErr('ng');

  function ensure(obj, name, factory) {
    return obj[name] || (obj[name] = factory());
  }

  var angular = ensure(window, 'angular', Object);

  // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
  angular.$$minErr = angular.$$minErr || minErr;

  return ensure(angular, 'module', function() {
    /** @type {Object.<string, angular.Module>} */
    var modules = {};

    /**
     * @ngdoc function
     * @name angular.module
     * @module ng
     * @description
     *
     * The `angular.module` is a global place for creating, registering and retrieving Angular
     * modules.
     * All modules (angular core or 3rd party) that should be available to an application must be
     * registered using this mechanism.
     *
     * When passed two or more arguments, a new module is created.  If passed only one argument, an
     * existing module (the name passed as the first argument to `module`) is retrieved.
     *
     *
     * # Module
     *
     * A module is a collection of services, directives, filters, and configuration information.
     * `angular.module` is used to configure the {@link auto.$injector $injector}.
     *
     * ```js
     * // Create a new module
     * var myModule = angular.module('myModule', []);
     *
     * // register a new service
     * myModule.value('appName', 'MyCoolApp');
     *
     * // configure existing services inside initialization blocks.
     * myModule.config(['$locationProvider', function($locationProvider) {
     *   // Configure existing providers
     *   $locationProvider.hashPrefix('!');
     * }]);
     * ```
     *
     * Then you can create an injector and load your modules like this:
     *
     * ```js
     * var injector = angular.injector(['ng', 'myModule'])
     * ```
     *
     * However it's more likely that you'll just use
     * {@link ng.directive:ngApp ngApp} or
     * {@link angular.bootstrap} to simplify this process for you.
     *
     * @param {!string} name The name of the module to create or retrieve.
     * @param {!Array.<string>=} requires If specified then new module is being created. If
     *        unspecified then the module is being retrieved for further configuration.
     * @param {Function=} configFn Optional configuration function for the module. Same as
     *        {@link angular.Module#config Module#config()}.
     * @returns {module} new module with the {@link angular.Module} api.
     */
    return function module(name, requires, configFn) {
      var assertNotHasOwnProperty = function(name, context) {
        if (name === 'hasOwnProperty') {
          throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
        }
      };

      assertNotHasOwnProperty(name, 'module');
      if (requires && modules.hasOwnProperty(name)) {
        modules[name] = null;
      }
      return ensure(modules, name, function() {
        if (!requires) {
          throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
             "the module name or forgot to load it. If registering a module ensure that you " +
             "specify the dependencies as the second argument.", name);
        }

        /** @type {!Array.<Array.<*>>} */
        var invokeQueue = [];

        /** @type {!Array.<Function>} */
        var runBlocks = [];

        var config = invokeLater('$injector', 'invoke');

        /** @type {angular.Module} */
        var moduleInstance = {
          // Private state
          _invokeQueue: invokeQueue,
          _runBlocks: runBlocks,

          /**
           * @ngdoc property
           * @name angular.Module#requires
           * @module ng
           * @returns {Array.<string>} List of module names which must be loaded before this module.
           * @description
           * Holds the list of modules which the injector will load before the current module is
           * loaded.
           */
          requires: requires,

          /**
           * @ngdoc property
           * @name angular.Module#name
           * @module ng
           * @returns {string} Name of the module.
           * @description
           */
          name: name,

          /**
           * @ngdoc method
           * @name angular.Module#provider
           * @module ng
           * @param {string} name service name
           * @param {Function} providerType Construction function for creating new instance of the
           *                                service.
           * @description
           * See {@link auto.$provide#provider $provide.provider()}.
           */
          provider: invokeLater('$provide', 'provider'),

          /**
           * @ngdoc method
           * @name angular.Module#factory
           * @module ng
           * @param {string} name service name
           * @param {Function} providerFunction Function for creating new instance of the service.
           * @description
           * See {@link auto.$provide#factory $provide.factory()}.
           */
          factory: invokeLater('$provide', 'factory'),

          /**
           * @ngdoc method
           * @name angular.Module#service
           * @module ng
           * @param {string} name service name
           * @param {Function} constructor A constructor function that will be instantiated.
           * @description
           * See {@link auto.$provide#service $provide.service()}.
           */
          service: invokeLater('$provide', 'service'),

          /**
           * @ngdoc method
           * @name angular.Module#value
           * @module ng
           * @param {string} name service name
           * @param {*} object Service instance object.
           * @description
           * See {@link auto.$provide#value $provide.value()}.
           */
          value: invokeLater('$provide', 'value'),

          /**
           * @ngdoc method
           * @name angular.Module#constant
           * @module ng
           * @param {string} name constant name
           * @param {*} object Constant value.
           * @description
           * Because the constant are fixed, they get applied before other provide methods.
           * See {@link auto.$provide#constant $provide.constant()}.
           */
          constant: invokeLater('$provide', 'constant', 'unshift'),

          /**
           * @ngdoc method
           * @name angular.Module#animation
           * @module ng
           * @param {string} name animation name
           * @param {Function} animationFactory Factory function for creating new instance of an
           *                                    animation.
           * @description
           *
           * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
           *
           *
           * Defines an animation hook that can be later used with
           * {@link ngAnimate.$animate $animate} service and directives that use this service.
           *
           * ```js
           * module.animation('.animation-name', function($inject1, $inject2) {
           *   return {
           *     eventName : function(element, done) {
           *       //code to run the animation
           *       //once complete, then run done()
           *       return function cancellationFunction(element) {
           *         //code to cancel the animation
           *       }
           *     }
           *   }
           * })
           * ```
           *
           * See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and
           * {@link ngAnimate ngAnimate module} for more information.
           */
          animation: invokeLater('$animateProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#filter
           * @module ng
           * @param {string} name Filter name.
           * @param {Function} filterFactory Factory function for creating new instance of filter.
           * @description
           * See {@link ng.$filterProvider#register $filterProvider.register()}.
           */
          filter: invokeLater('$filterProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#controller
           * @module ng
           * @param {string|Object} name Controller name, or an object map of controllers where the
           *    keys are the names and the values are the constructors.
           * @param {Function} constructor Controller constructor function.
           * @description
           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
           */
          controller: invokeLater('$controllerProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#directive
           * @module ng
           * @param {string|Object} name Directive name, or an object map of directives where the
           *    keys are the names and the values are the factories.
           * @param {Function} directiveFactory Factory function for creating new instance of
           * directives.
           * @description
           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
           */
          directive: invokeLater('$compileProvider', 'directive'),

          /**
           * @ngdoc method
           * @name angular.Module#config
           * @module ng
           * @param {Function} configFn Execute this function on module load. Useful for service
           *    configuration.
           * @description
           * Use this method to register work which needs to be performed on module loading.
           */
          config: config,

          /**
           * @ngdoc method
           * @name angular.Module#run
           * @module ng
           * @param {Function} initializationFn Execute this function after injector creation.
           *    Useful for application initialization.
           * @description
           * Use this method to register work which should be performed when the injector is done
           * loading all modules.
           */
          run: function(block) {
            runBlocks.push(block);
            return this;
          }
        };

        if (configFn) {
          config(configFn);
        }

        return  moduleInstance;

        /**
         * @param {string} provider
         * @param {string} method
         * @param {String=} insertMethod
         * @returns {angular.Module}
         */
        function invokeLater(provider, method, insertMethod) {
          return function() {
            invokeQueue[insertMethod || 'push']([provider, method, arguments]);
            return moduleInstance;
          };
        }
      });
    };
  });

}
<|endoftext|>