diff --git a/.idea/HiPyProject.iml b/.idea/HiPyProject.iml deleted file mode 100644 index d0876a7..0000000 --- a/.idea/HiPyProject.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 5bbe586..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 63b27af..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index 8eb4239..0000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1557812616712 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CNAME b/CNAME deleted file mode 100644 index e9f93a9..0000000 --- a/CNAME +++ /dev/null @@ -1 +0,0 @@ -hipy.uk diff --git a/Machine Learning Helper Notebook.ipynb b/Machine Learning Helper Notebook.ipynb deleted file mode 100644 index e759a75..0000000 --- a/Machine Learning Helper Notebook.ipynb +++ /dev/null @@ -1,116 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Machine Learning Hive Beekeeper Notebook\n", - "\n", - "This is a working notebook for common questions/information about the Machine Learning modules and hives. While writing this, I've gone through the modules again and tried to answer any questions I think might come up here, so you won't have to fiddle around with google on the day - of course, I'll probably miss things so feel free to add stuff!\n", - "\n", - "This module has a few aims:\n", - "\n", - "* Explain some common algorithms, the thinking behind them and how they can be applied to real world problems.\n", - "* To get people used to using 3rd party \"black box\" libraries, and to start to understand why libraries are so helpful in general.\n", - "* To give illustrations of how powerful data analysis/science is using Python (or indeed any other coding language).\n", - "* To serve as a soft introduction into the world of neural networks if people want to go down that route.\n", - "\n", - "It's organised as one algorithm per notebook, in a very simple format of explaining the algorithm, example code, and a project that is slightly more challenging than the example but shouldn't be unreasonable given the person doing it has a solid foundation of Python. Naturally I think the first questions people will ask are:\n", - "\n", - "### Why do machine learning over statistics?\n", - "\n", - "Machine learning and statistics are similar areas, and often use the same methods in finding an answer (for example, regression), but the difference comes from their implementation in Python - machine learning libraries such as scikitlearn will build a model object we can make predictions from, whereas stats libraries like scipy and statsmodels are more useful for getting statistical summaries like test statistics and p-values. In practice, it depends on the application - if you are running an experiment and need to see the correlation between two variables, you will probably want to use a statistics package, but if you are building a model to predict where earthquakes might hit, you will probably want to use machine learning.\n", - "\n", - "### It's all good knowing these models - but what model do I need to apply?\n", - "\n", - "A lot of this depends on what you are trying to achieve and what data you have - do we want to categorise data into sets or do we want to find a continuous relationship between them? Do we need the results to be fast or accurate? Do we have a training set we can use the model for? All of these questions help us decide what model we want to use (sometimes the answer isn't just to slam it into a neural network!)\n", - "\n", - "# K Means Clustering\n", - "\n", - "### How do I choose k? Surely there has to be a better way than the elbow method?\n", - "\n", - "This is where knowledge of your field comes in - for example, if you are trying to cluster population centers, you will use k values that make sense for the area (number of cities etc).\n", - "\n", - "### What's going on with the make_blobs function?\n", - "\n", - "Get them to print everything the make_blobs function give us - it will give a list, with the points in the first index, and a lot of stuff we don't need (in fact, the list is the list which gives a corresponece from each point to the blob it belongs in!). For our example, we don't want to other stuff, so we just index it out.\n", - "\n", - "### What's the indexing trick?\n", - "\n", - "Our data is a 2 column matrix - each row is a point which we want to plot - since matplotlib wants a list of x coordinates then a list of y coordinates, we need to format the data to get it into a position we can use the plot function on it. The indexing in numpy works by giving what is basically a list of slices - since we want to index all rows we put the empty slice \":\" in the first spot, and \"0\" for the second spot because we only want everything from the first column. Similarly, we use [:,1] for the y values because we want every row, but every second value for each row.\n", - "\n", - "Also consider the native Python equivilent and how they would do it then using indexing and/or for loops. It's much more of a pain!\n", - "\n", - "### Completely confused about the \"model\" variable, what does it mean?\n", - "\n", - "This is a product of object orientated programming - we actually initialise a k means model for 4 centers using the KMeans() function, and then fit it to our data using the fit method. This is a method on the model object - not a function - so the model \"changes itself\" to fit our data. What's important to realise is all the information we need is stored inside the model object, we don't get it from running functions on it!\n", - "\n", - "\n", - "### How can I do Mini Project 1 if the data is 4 dimensional?\n", - "\n", - "The great thing about the algorithm is that it's generalised - we don't care about what these points represent (see project 2), and how many dimensions our data points have - the reason this is a 4 dimensional example is to remove the crutch of geometric representation - you have to trust in the code! \n", - "\n", - "The solution for this Mini Project is pretty much identical for the example but backwards - we want to use the elbow method first to find a suitable K and then build a model using the suitable k. People who are struggling might try and guess for values of K - try and get these people to think about why that might not be a good idea (model always gets better for larger k, but that's not the point of the model! We don't want to overfit). People who are excelling through this might wonder if there's a better way of finding a K-value suitable for our data. In fact, there is a better algorithm for when we don't know our K-value called the DBSCAN method - but I haven't written this guide yet!\n", - "\n", - "### How do I get started on Mini Project 2? There's no numbers!\n", - "\n", - "Explain how RGB values work - everything else pretty much follows from here - I think it's a numpy function to convert a picture to RGB\n", - "\n", - "### What is K for Mini Project 2?\n", - "\n", - "If we want to quantise for 16 colours - what does this mean?\n", - "\n", - "\n", - "# K Nearest Neighbours\n", - "\n", - "Most of the questions above also apply to this guide - I decided to move a bit faster at this point because I'm expecting people to be getting more comfortable with numpy and pandas at this point. The most confusion will come from the illustration of KNN - I think people will be able to understand it at this point but might need some help understanding certain bits of the code. The idea is that we set upper and lower bounds for x and y based on our data, with a buffer of 1 so the graph has a bit of space, then set up a meshgrid, which is basically a 2 dimensional matrix with each point on the graph being represented. We then need to format this a little to get it into (x,y) pairs, which we will have one of for each point on the graph. Then we predict every one of these points and plot it behind our actual data to show the boundry.\n", - "\n", - "# Support Vector Machines\n", - "\n", - "### Why use this vs the KNN algorithm?\n", - "\n", - "First priority is data - if you need a linear seperation between your data KNN isn't going to give you that. Other than that, SVM is a much slower algorithm than KNN, so if we don't need to be accurate but need to be fast, then SVM might not be appropriate.\n", - "\n", - "# Decision Trees\n", - "\n", - "### Why use it?\n", - "\n", - "Gives us a fast model that we can use as humans to classify data even if it's multidimensional. Great when speed and explaination are needed over a \"black box\" and accuracy!\n", - "\n", - "### How do I get those fancy visualiations?\n", - "\n", - "Honestly, this took me the best part of 4 hours to do. Get them to google it and figure it out for their system - knowing how these events run nothing will run the same on my system compared to anyone elses!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.3" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/PurePy 0. Woffle and Getting Started/.ipynb_checkpoints/0.1 Introduction-checkpoint.ipynb b/PurePy 0. Woffle and Getting Started/.ipynb_checkpoints/0.1 Introduction-checkpoint.ipynb deleted file mode 100644 index 77fca81..0000000 --- a/PurePy 0. Woffle and Getting Started/.ipynb_checkpoints/0.1 Introduction-checkpoint.ipynb +++ /dev/null @@ -1,182 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![Header2](header1.png)\n", - "\n", - "# What is Python?\n", - "\n", - "Ever wanted to learn to code? Maybe there are some tasks you do over and over that you'd love to get a computer to do them for you. Perhaps you've got an idea for an app, but no way to make it happen. Or maybe you've heard that coding is an important skill in today's economy and want to get ahead. Maybe you're just curious.\n", - "\n", - "Or maybe you already know how to code? Perhaps you know one of the heavy-duty langauges like C++ or Java, but want something more fun for you smaller projects. Perhaps you're a science student raised on MATLAB, looking for a more widely available alternative for when you get out in the real world.\n", - "\n", - "Python is a free programming language created and maintained by Dutch programmer Guido Von Rossom. It's designed designed to be easy to read and learn, with many aspects of the language reading like English, and many technical aspects of programming handled \"behind the scenes\". This makes Python a great first language, and its quick-and-easy approach makes it a great tool even for seasoned programmers.\n", - "\n", - "The other side of the coin of \"what is Python?\" is analogous to the other side of the question \"What is English?\". On the one hand, it is a Germanic language, originating in England and spoken throughout the world. On the other, it is the canon of literature written in English, and the community of English speakers. Similarly, Python is the vast array of Python code that has already been written, much of it freely available online, so that other programmers may find it useful. These Python \"libraries\" offer tools for almost everything, from creating websites to analysing DNA sequences.\n", - "\n", - "Computers don't understand programming languages. They understand machine code, which is basically unreadable to humans. Therefore, a program must translate the source code, written in Python or another programming language, into machine code, which the computer can understand. This software for us is called a Python interpreter. We will sometimes be lazy with our language, and refer to the Python interpreter simply as \"Python\", as in \"Python won't understand what you mean if you type this wrong\", or \"Run Python\" (meaning \"Run a Python interpreter\").\n", - "\n", - "At HiPy, we recommend installing [Anaconda](https://www.continuum.io/downloads), which is the regular Python interpreter and standard library, plus many more great libraries and development tools. It's a big download, but having all the best tools right in front of you from the start is worth the payoff, in our opinion.\n", - "\n", - "\n", - "# Three main ways to execute Python code\n", - "\n", - "So, let's assume you've installed Python (there we go already, lazily referring to the standard Python interpreter + libaries as \"Python\"), possibly via Anaconda. How do we get stuff to happen? Well, there are three main ways that you can start using Python right now. Each has different advantages for different situations.\n", - "\n", - "### Quick start note: Don't care about this stuff and want to just get on with PurePy 1? Run Spyder from the Anaconda launcher. Type code on the left of the screen, and hit $\\blacktriangleright$ to run it. The result will appear on the right.\n", - "\n", - "## Interactively\n", - "\n", - "Once Python is correctly installed, opening a command-line interface (see PurePy 0.2 for more on the command-line) and typing python will bring up something that looks like this:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "Python 3.6.1 |Anaconda 4.4.0 (64-bit)| (default, May 11 2017, 13:09:58) \n", - "[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux\n", - "Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n", - ">>>" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This is the interactive Python shell, and those three little >'s mean Python is ready to talk to you. You can type anything in here, and the interpreter will try to read it as if it is Python code. It will execute the line of code you typed, and then tell you the result.\n", - "\n", - "So the stuff we type has to be Python code. We cannot just say \"hello\", but if we do, nothing bad will happen. The interpreter just lets us know that this is not what it was expecting." - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - ">>> Hello Python!\n", - " File \"\", line 1\n", - " Hello Python!\n", - " ^\n", - "SyntaxError: invalid syntax\n", - ">>>" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Try some arithmetic. The Python shell understands this at the very least:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - ">>> 5 / 2\n", - "2.5\n", - ">>>" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The interactive interface for Python has three main uses:\n", - "\n", - "- Performing very quick computations.\n", - "- Testing bits of code before adding them to a big program.\n", - "- Interacting with a program you've already written.\n", - "\n", - "The downsides are that you can't easily save what you've done. Without some effort, both your code and results are gone at the end of your session. This furthermore means that larger programming endeavours are unfeasible, because you can't just save your code and come back later.\n", - "\n", - "### IPython vs. Python\n", - "\n", - "An alternative version of the interactive Python interpreter exists called IPython, and it comes installed with Anaconda. It has loads of extra features to make inteteractive computing with Python easier, faster, and more readable. Both run the same code in the same way. The only downside, as I see it, to IPython is that it takes a few moments longer to start up.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Scripts: Editor + Interpreter\n", - "\n", - "So interactive computing is all well and good. But most of the time we want to write a larger program, that can perform more elaborate tasks, and we don't want to have to feed each step to the interpreter one at a time.\n", - "\n", - "So the alternative is to write all your code in a file, and then pass it to the Python interpreter to read through and execute. The Python file is called Python script, or Python module. Any software that can write a file of text can be used to write a Python module, but some are more suited to this task than others.\n", - "\n", - "### Important note\n", - "\n", - "When you are using Python interactively, the result of every computation is written to the screen as output. If you are running a Python script written in a text file, which may be thousands of lines long, it is unlikely that you will want to see the result of every single computation along the way. To see the result of a computation, use the print() command, for example, print(5 / 2) will display 2.5 to the screen.\n", - "\n", - "### IDEs\n", - "\n", - "An IDE is an \"integrated development environment\". Generally this means it's a piece of software that brings all the tools needed to write a program under one roof. So, the IDE will contain a text editor, for writing code. It may include a terminal, so you can access your computer's command line interface. It may include a Python interpreter, as well as debugging tools, version control, a file manager, and anything else a developer might need.\n", - "\n", - "![Spyder](SpyderPython 3.6_112.png)\n", - "\n", - "Included with Anaconda, Spyder is a perfectly fine IDE to start with that runs the IPython interface alongside the editor window. If you installed Anaconda, this is an easy way for you to get started! If, after a while, you're looking for something with more features, try PyCharm. If you're looking for something with less features that loads faster, try Geany.\n", - "\n", - "### Text editors\n", - "\n", - "While IDEs provide many conveniences, many Python programmers prefer to edit text in a specialized programming text editor, and then run their program from the command-line. A good text editor is really, really good at efficiently editing text. The various extra features provided by IDEs can be handled with other programs. At the very least, a programming text editor should have syntax highlighting, in which the text is displayed in different colours to show the structure of the program.\n", - "\n", - "A great choice for a programming text editor is [Atom](https://atom.io/), for any system, or [Notepad++](https://notepad-plus-plus.org/download/v6.9.1.html) if you're on Windows. Some popular text editors, like VIM and Emacs, are very powerful, but take days to learn to use -- learn Python first before deciding if it is worth your investment!\n", - "\n", - "![The Atom Text Editor](atom-python.png)\n", - "\n", - "If you choose this approach, definitely check out PurePy 0.2 about the command-line.\n", - "\n", - "Once you have written your text file, save it with the extension .py. Then you can go to your command line, navigate to the directory containing that file, and type python fileyoujustmade.py to run it.\n", - "\n", - "## Jupyter Notebook\n", - "\n", - "This is a sort of hybrid between interactive and scripted Python. It is the Jupyter notebook, in which this document was created. Think of it as an interactive document, which talks to a Python interpreter and allows code to be written and executed, displaying the output within the document itself. It also, of course, allows segments of text to explain the code, supports $\\LaTeX$ for mathematical typesetting, and can display picture and other media. This makes Jupyter notebook great for data analysis, as your methodology (your code) and results (plots and such) can be displayed together in a single document. You can launch Juypter notebook from Anaconda, or from the command line with the command jupyter-notebook.\n", - "\n", - "Many online services, such as [CoCalc](www.cocalc.com) or [Azure](https://notebooks.azure.com/) offer online and collaborative Jupyter notebooks.\n", - "\n", - "To get started on Jupyter, write code in a cell, and hit shift+return to execute the code in the cell. If you want a cell to contain text, use the dropdown menu at the top of the screen to switch the cell type from \"Code\" to \"Markdown\"." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# What next?\n", - "\n", - "If you want to get started learning some Python programming now, skip ahead to PurePy 1. Alternatively, PurePy 0.2 provides a crash course in command-line computing, an important secondary skill for anyone doing programming. However, you will not lose out if you skip it for now and come back to it later, since presumably you came to HiPy to learn Python!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.1" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/PurePy 0. Woffle and Getting Started/.ipynb_checkpoints/0.2 The command line-checkpoint.ipynb b/PurePy 0. Woffle and Getting Started/.ipynb_checkpoints/0.2 The command line-checkpoint.ipynb deleted file mode 100644 index e306d2c..0000000 --- a/PurePy 0. Woffle and Getting Started/.ipynb_checkpoints/0.2 The command line-checkpoint.ipynb +++ /dev/null @@ -1,473 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# The command line: a very short introduction\n", - "\n", - "This article is not about Python. But it is worth the time of any new Python programmer, or anyone who uses computers a lot. We have to have a discussion about the command-line. Most of us in the modern era have grown up using a graphical user interface (GUI) to interact with our computers. This is where we use a mouse or touch screen to press on-screen buttons, drag-and-drop files, highlight text, move a scroll bar, or bring up a menu. But there is another method, in which we interact with the computer by typing in text commands, and getting text output. For many, this is an ancient relic seen only in films such as The Matrix, War Games, or Hackers, but in the world of computers and computer programming, it remains an invaluable tool.\n", - "\n", - "Now the command-line isn't pretty, and takes a little practice to learn. Most commercial software is no longer written for the command-line for this reason. But as Python beginners, we're generally going to be writing programs that:\n", - "1. Takes some input,\n", - "2. Performs some task or computation,\n", - "3. Gives some output,\n", - "\n", - "rather than writing commercial software. For this purpose, a text-based, command-line is quicker, easier, and just as effective.\n", - "\n", - "Reasons to learn basic command-line skills:\n", - "- Command-line software is easier to write than graphical software.\n", - "- Many tasks easier and faster with the command-line.\n", - "- Access to vast repositories of free command-line software.\n", - "- More freedom to tinker with the workings of your computer.\n", - "- Feel like a hacker.\n", - "\n", - "That said, there are still many tasks which lend themselves better to the graphical interface. I don't know many people, for instance, who manage their emails from the command-line (though such people almost certainly exist). It's just about choosing the correct tool for the job." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Before we begin, three basic terms. A command-line is any computer interface in which you type text and get text back. A terminal or terminal emulator is a piece of software on your computer that displays the text for a command-line interface. Finally, a shell is the software \"behind the scenes\", that interprets your commands, performs the tasks you ask of it, and then displays the result in your terminal. These words are sometimes used somewhat interchangeably. Something like \"type this command into the command-line\", \"type this command into the terminal\", \"type this command into the shell\" all mean basically the same thing." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Accessing a command-line\n", - "\n", - "The precise software you use will depend on your operating system. If it is at all possible, you should try to use the Bash shell. This has become the standard shell across Mac OSX and Linux operating systems. It is now also available as an experimental feature of Windows 10: see [here](https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/) for installation instructions. If you are on Windows, but either you do not have Windows 10 or you do not want to install Bash for some reason, then you can use a software that comes with Windows call Powershell. The most basic commands of Powershell and Bash are roughly the same, and most of the things we learn in this tutorial are applicable to Bash and Powershell.\n", - "\n", - "* On Windows, either follow the Bash instructions above, or go to the Start Menu, type Powershell, and open the software it suggests. Note that in Powershell you might have to use backslashes instead of slashes for file paths.\n", - "* On OSX, press cmd+space. This will open the spotlight, which can access any file or program on your computer. Type Terminal, and you will shown the correct software on the menu. Consider adding the terminal to your dock, as it is very useful to have quick access.\n", - "* On Linux systems, go to whatever interface you usually use to open software. If you're on Ubuntu or GNOME or something, try the gnome-terminal, usually accessible just be typing \"Terminal\". If you are on another operating system, you might not have gnome-terminal, but you will definitely have xterm or some equivalent, so try searching for xterm.\n", - "\n", - "Now after allowing everything to load, you should see some kind of command-prompt. On Powershell, I think it will end with a > symbol. In Bash, it will probably be a $ sign. This means the command-line is ready to take commands." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Will I break my computer?\n", - "\n", - "Probably not. There are several checks to make sure you do not do anything dangerous unwittingly. The command for deleting files requires special permissions to delete entire folders, for example. In Bash, many commands that involve installing software, changing important settings or modifying key system files will require you to log-in as an administrator or enter an administrator password before proceeding (even if you are already logged in as an administrator in your normal graphical session).\n", - "\n", - "## Anatomy of a command\n", - "\n", - "A command has the structure \"command options arguments\". The command is a program we'd like to run, or an action we'd like to take. For example, if I open my terminal and simply type firefox, then it opens my web browser. Many commands and programs run inside the terminal, unlike Firefox. Options are things we can add to change the way the command works, often beginning with a - or --, and then a letter or word (for example, it is common in Bash that to get help for using a program, you follow the name of the command with --help. Finally, the arguments are inputs to a command.\n", - "\n", - "As an example, a very simple Bash program called cat can be used to show the contents of a text file in the terminal window. If I just type cat, then the program waits for me to type some text for it to display. If I type cat A_FILE_NAME, then the contents of that file will be displayed: the file name is an argument, an input to the program. Finally, as an example of using it with an option, cat --number A_FILE_NAME. This will display the contents of a file with line numbers shown.\n", - "\n", - "You can usually see what the options are for a program by running PROGRAM_NAME --help or running man PROGRAM_NAME, that is, the program \"manuals\" with the name of the program you want help with as an argument." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## The working directory\n", - "\n", - "The first command we will learn is pwd, which stands for \"print working directory\". This means \"print onto the screen\", not \"print from your printer\". The working directory is the folder in your computer that you are currently \"in\", just like on a graphical file browser (My Computer, Finder, nautilus, etc), you are usually viewing and manipulating the contents of just one folder.\n", - "\n", - "For instance, when I open my terminal and type pwd, I have something like:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ pwd\n", - "/home/sam" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This shows us where we currently are in our computer's file system. The natural thing to want to do is to view the contents of the current working directory. Just type ls, which is short for \"list\", if I'm not mistaken. Now you should see the contents of the current directory, possibly with colour coding to show different kinds of file if your terminal is fancy enough." - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ ls\n", - "Desktop Pictures\n", - "Documents Public\n", - "Downloads Templates\n", - "Music Videos" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Cool, so now we are starting to orientate ourselves in our computer. In Bash, there are many useful options for ls. For example, ls -a is \"list all\", which shows hidden files (usually files containing settings for programs, which you will only edit occasionally and otherwise get in the way. Hidden files start with a .). You can use ls -l for a more detailed list with file sizes and such. Options that are of one letter can often be joined into one option, so ls -l -a can be ls -la, which will display a detailed list of all the files in your directory.\n", - "\n", - "If you provide a path to a directory to ls as an argument, it will list the contents of that directory instead:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ ls Documents\n", - "Personal\n", - "Work\n", - "Articles\n", - "Letters" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Changing directory\n", - "\n", - "Now we learn how to navigate. The command cd, when given a directory as an argument, will change the current working directory. Example:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ pwd\n", - "/home/sam\n", - "$ cd Documents\n", - "$ pwd\n", - "/home/sam/Documents" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can go \"up\" a directory by navigating to ..:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ pwd\n", - "/home/sam\n", - "$ cd Documents\n", - "$ pwd\n", - "/home/sam/Documents\n", - "$ cd ..\n", - "$ pwd\n", - "/home/sam" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If you need to refer to a folder or file with spaces in, put the file name in quote marks." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Relative and absolute paths\n", - "\n", - "So far, we have used relative file paths. This is where the \"route\" taken to the desired directory or file is relative to the current working directory. In the above example, cd Documents took me to Documents because Documents is contained in the current working directory. If my current working directory were, say, home/sam/Pictures, then to navigate to the Documents directory in one move, I could use cd ../Documents, meaning \"go up one level, and then go to Documents\".\n", - "\n", - "However, I can also use what is called an absolute path. This is an exact address, always referring to the same file or directory regardless of the current working directory. In Mac OSX/Linux, starting a path with / makes it absolute. Hence if I am in the Pictures folder (or indeed ANY folder) and want to go to Documents, I can always type" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ cd /home/sam/Documents\n", - "$ pwd\n", - "/home/sam/Documents" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "On Windows Powershell, you can give an absolute path by starting the path with the drive name, like" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "> cd C:\\Users\\Sam\\Documents" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Making a new directory\n", - "\n", - "The command to make a new directory is mkdir, and the directory name is provided as an argument:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ ls\n", - "Desktop Pictures\n", - "Documents Public\n", - "Downloads Templates\n", - "Music Videos\n", - "$ mkdir python-scripts\n", - "$ ls\n", - "Desktop python-scripts\n", - "Documents Public\n", - "Downloads Templates\n", - "Music Videos\n", - "Pictures " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that I chose to use a - instead of a space in my directory name. As a regular user of the command line, this makes it easier to type as I don't have to remember to put it in quotes this way." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Tab completion\n", - "\n", - "One of the nicest features about modern command-lines is that they often allow tab completion. Pressing the TAB key when partway through a command or file in the current directory will complete the command for you, if there is only one possibility. For example, in my /home/sam directory, typing cd Doc and hitting TAB will complete the command to cd Documents. This allows for much more rapid navigation and manipulation.\n", - "\n", - "## Move, copy, or rename a file\n", - "\n", - "It may surprise you that on the command-line, moving and renaming files are the very same command. It's quite simple really. The mv command takes two arguments: the first, a source file; the second, a target. If the target is a directory, the file is moved to that directory" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Delete a file\n", - "\n", - "Delete a file with the command rm, followed by the name of the file relative to the current working directory. If you want to delete a folder, you will have to use rm -r DIRECTORY_NAME. This -r stands for \"recursive\" and means \"delete the contents and the folder\"." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Make a new text file\n", - "\n", - "In bash, you can use the command nano followed by a file name (if it doesn't exist it will be created) to open the nano text editor, an easy-to-use terminal-based text editor. Here you can type a Python file, or any other text file you like. The basic commands are given at the bottom (the ^ sign refers to the ctrl key, so to save (\"write out\") a file is ctrl+O. The text editor has syntax highlighting based on the file name, so ending the file name with .py will enable Python highlighting; in other words, the colours will change to reflect the structure of Python code, if you terminal supports colours.\n", - "\n", - "On Windows Powershell, you can use notepad.exe FILENAME to achieve a similar end." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Access Python\n", - "\n", - "Well, now we get to the business end. You know how to navigate through your computer and even write a Python program using nano. If Python is installed correctly, and your shell knows where it is, typing python should open the interactive Python interpreter, a command-line interface with a shell that understands Python commands, rather than Bash or Powershell commands. You should see something like this. The >>> means it is ready to start interpreting Python commands." - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ python\n", - "Python 3.6.1 |Anaconda 4.4.0 (64-bit)| (default, May 11 2017, 13:09:58) \n", - "Type \"copyright\", \"credits\" or \"license\" for more information.\n", - ">>>" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From here, we can type any valid Python code and the program will run it. Since we don't know any Python yet, just test it by asking it \"2 + 2\":" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - ">>> 2 + 2\n", - "4" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can leave by typing exit().\n", - "\n", - "Next we'll learn how to run a Python program that you have already written. Type nano hello.py or notepad.exe hello.py. This has made a new Python file. In the file, write" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "print(\"Hello world!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "and save it (ctrl+O in nano), then exit (ctrl+X in nano). This program, if written correctly, will write \"Hello world!\" on the screen.\n", - "\n", - "Then, when in the working directory in which you saved the file, type:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ python hello.py\n", - "Hello world!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Hence, python is the program, and hello.py is the argument provided. Now you know how to run any Python file, even one you have downloaded from the Internet.\n", - "\n", - "### Did you get an error when you typed python, even though you installed it fine?\n", - "\n", - "It means that python is not in your shell's PATH variable. Don't worry. The idea is, when you type a command, it would be very slow (and risky) for the shell to just search your entire computer for some program that command could refer to. Instead, there is a list called PATH of places the shell should look to find programs.\n", - "\n", - "So, to solve this, you must find where you have installed Python, and then tell your computer that it's okay to look here when you give it a command.\n", - "\n", - "If you're using Bash:\n", - "1. Navigate to your home folder. The quick way is cd ~, since ~ always refers to your home folder, for convenience.\n", - "2. You need to edit a file called .bashrc. The ., recall, means it is a hidden file. This is just a file that contains settings for your Bash sessions.\n", - "3. Hence, type nano .bashrc. There might already be a bunch of stuff in here. If you're feeling bored but brave sometime, feel free to back up this file and have a play around to see what happens.\n", - "4. Scroll down to the bottom of the file. Add the line:\n", - "\n", - "\n" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "export PATH=\"/path/to/folder/where/python/is/installed:$PATH\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This just means \"change the PATH variable to '/path/to/where/python/is/installed' followed by whatever the PATH variable was before\". Save the file and exit, then type exit into Bash. Open the terminal again and Python should work.\n", - "\n", - "If you're using Windows Powershell\n", - "\n", - "Type into Powershell\n", - "\n", - "[Environment]::SetEnvironmentVariable(\"Path\", \"$env:Path;C:\\path\\to\\folder\\where\\python\\is\\installed\")\n", - "\n", - "This should solve it.\n", - "\n", - "If neither of these work, I'm afraid you'll have to get your Google-fu on." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Still a bit baffled? Check out the video\n", - "\n", - "All of these basic commands are demonstrated in the video below. You'll see that it's pretty easy once you get going.\n", - "\n", - "\n", - "If you're interested in learning more about how to use Bash and become a command-line expert, there's a great free e-book called The Linux Command Line by William E. Shotts Jr." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from IPython.display import YouTubeVideo\n", - "YouTubeVideo(\"poUKA4pOn7k\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Exercise\n", - "\n", - "From the command line, create a folder in your home directory for \"Python-and-computer-notes\" or something. In here, use the nano text editor to write a short summary of everything you learned here, and save it for future reference." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.1" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/PurePy 11. Exceptions/.ipynb_checkpoints/Exceptions, and debugging-checkpoint.ipynb b/PurePy 11. Exceptions/.ipynb_checkpoints/Exceptions, and debugging-checkpoint.ipynb deleted file mode 100644 index 194531e..0000000 --- a/PurePy 11. Exceptions/.ipynb_checkpoints/Exceptions, and debugging-checkpoint.ipynb +++ /dev/null @@ -1,452 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Handling exceptions, and debugging\n", - "\n", - "## Exceptions\n", - "\n", - "So far, errors have been the bane of our lives. We pass the wrong kind of argument to a function, we make an accidental division by 0, or we try to access a list element that doesn't exist. The whole program crashes, and we're frustrated trying to find out what went wrong.\n", - "\n", - "Now we can turn this situation on its head. Python lets us anticipate places where errors might occur, and allows us to tell the program what to do if it encounters an error, instead of coming grinding to a halt. In other words, we can put our errors to work for us.\n", - "\n", - "\"Great!\" you might be thinking. \"I'll just ignore all errors!\" Not so fast, of course. The point of error messages is they tell us where our program is going wrong and prevents more serious problems happening further down the line. We want to be informed when an unexpected error occurs as that means there's something wrong with our program. What exception handling allows us to do is manage the errors that we do expect to happen from time to time. This means our exception handling should be carefully tailored to the circumstances." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### raise\n", - "\n", - "The raise keyword is followed by the name of an exception (a procedure that occurs when an error occurs), and causes that kind of exception to occur. We can also provide an error message to go with the error" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "This is the wrong type of thing", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"This is the wrong type of thing\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m: This is the wrong type of thing" - ] - } - ], - "source": [ - "raise TypeError(\"This is the wrong type of thing\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This can be used along with if statements to only raise the exception under specific circumstances. Suppose I have a function that is supposed to operate on lists:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def acts_on_a_list(a_list):\n", - " for x in a_list:\n", - " print(x)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now before calling that function, I might write:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "letters variable should be a list", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mletters\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m'S'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'a'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'm'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mletters\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"letters variable should be a list\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0macts_on_a_list\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mletters\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mTypeError\u001b[0m: letters variable should be a list" - ] - } - ], - "source": [ - "letters = ('S', 'a', 'm')\n", - "if not isinstance(letters, list):\n", - " raise TypeError(\"letters variable should be a list\")\n", - "acts_on_a_list(letters)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now you see, I have anticipated that my function might receive the wrong kind of input at this stage, and given the user an error message to explain what they are doing wrong.\n", - "\n", - "## try, except, finally\n", - "\n", - "Astute reads will have noticed that actually, my function acts_on_a_list() doesn't require a list at all. It could take as its input anything sequential, such as a tuple, a dictionary, a range object, or maybe things we haven't even considered. I don't want to have to create if... raise statements for every possible kind of input my function could take, right?\n", - "\n", - "This is where try comes in, and the mantra that \"It's easier to ask forgiveness than permission\". In short, try does what it says on the tin: it tries to do something! The difference is that we can provide further instructions in case what it is trying to do goes wrong. This would be more appropriate:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "S\n", - "a\n", - "m\n" - ] - } - ], - "source": [ - "try:\n", - " acts_on_a_list(letters)\n", - "except TypeError:\n", - " print(\"acts_on_a_list was not provided with a sequence!\")\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "acts_on_a_list was not provided with a sequence!\n" - ] - } - ], - "source": [ - "try:\n", - " acts_on_a_list(42)\n", - "except TypeError:\n", - " print(\"acts_on_a_list was not provided with a sequence!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So this one didn't actually cause the error message. Instead, the exception was \"caught\" before the error message occurred, and a new bit of code was executed to say what happens next. This could be, for instance, performing an alternative version of the action:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "acts_on_a_list was not provided with a sequence!\n", - "E\n", - "x\n", - "a\n", - "m\n", - "p\n", - "l\n", - "e\n" - ] - } - ], - "source": [ - "try:\n", - " acts_on_a_list(42)\n", - "except TypeError:\n", - " print(\"acts_on_a_list was not provided with a sequence!\")\n", - " acts_on_a_list(\"Example\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Notice, we have precisely specified what kind of error we wish to catch: other kinds of errors will still occur in the usual way." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "ename": "IndexError", - "evalue": "list index out of range", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0macts_on_a_list\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"HiPy\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"Sam\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"acts_on_a_list was not provided with a sequence!\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0macts_on_a_list\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Example\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mIndexError\u001b[0m: list index out of range" - ] - } - ], - "source": [ - "try:\n", - " acts_on_a_list([\"HiPy\", \"Sam\"][3])\n", - "except TypeError:\n", - " print(\"acts_on_a_list was not provided with a sequence!\")\n", - " acts_on_a_list(\"Example\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This is a good thing -- remember, we usually only want to catch the expected errors, and still be alerted properly if something truly unexpected happens. It's possible to use pass to continue as if nothing happened" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Look, nothing happened\n" - ] - } - ], - "source": [ - "try:\n", - " acts_on_a_list(3.14)\n", - "except TypeError:\n", - " pass\n", - "print(\"Look, nothing happened\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And it seems like nothing happened. If we use except without providing the name of an exception, all exceptions will be handled in the same way (or ignored, if this is followed by pass). This is occasionally useful, but only if you know what you're doing -- specific, targeted errors are preferred. Here's a more practical little example of try, to add corresponding elements :" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def add_list_elements(listA, listB):\n", - " longest_list = max([listA, listB], key=len)\n", - " listC = [x for x in longest_list]\n", - " for i, value in enumerate(listC):\n", - " try:\n", - " listC[i] = listA[i] + listB[i]\n", - " except IndexError:\n", - " pass\n", - " return listC" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So we start by creating a copy of the longest list. Then for each index of the new list, we attempt to replace that list entry with the sum of the corresponding entries from the original of the two lists. If this fails due to an index error, which it eventually will if the lists are different sizes, we do nothing -- we just leave it as the same entry as the longer list:" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[15, 25, 3, 123, 4]\n" - ] - } - ], - "source": [ - "A = [5, 5, 3, 123, 4]\n", - "B = [10, 20]\n", - "print(add_list_elements(A,B))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can respond to different exceptions by giving them in sequence, as in:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "try:\n", - " something()\n", - "except Exception1:\n", - " do_this()\n", - "except Exception2:\n", - " do_that()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "try...except can be followed with an else clause, which occurs only if there was no exception.\n", - "\n", - "A final part can be added after a try...except block. This is finally. This is a piece of code that will run regardless of success, failure, caught or uncaught exceptions. It will run no matter what, even if the rest of your program comes crashing down.\n", - "\n", - "This is not unfamiliar -- it is precisely what with open() does when you open a file: it has a procedure for closing the file regardless of what happens while the file is open.\n", - "\n", - "As an example of a good time to raise an exception, recall the polynomial class we made in tutorial 10. Virtually nothing will work if the argument provided is not a sequence of numbers, so we might want to add a check:" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "class Polynomial(list):\n", - " def __init__(self, *coeffs):\n", - " from collections.abc import Sequence\n", - " from numbers import Number\n", - " if isinstance(coeffs[0], Sequence):\n", - " coeffs = coeffs[0]\n", - " if not isinstance(coeffs, Sequence):\n", - " raise TypeError(\"Argument should be a sequence of numbers\")\n", - " for x in coeffs:\n", - " if not isinstance(x, Number):\n", - " raise TypeError(\"Argument should be a sequence of numbers\")\n", - " \n", - " coeffs = list(coeffs)\n", - " list.__init__(coeffs)" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "Argument should be a sequence of numbers", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mPolynomial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'a'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m5\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, *coeffs)\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mcoeffs\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mNumber\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Argument should be a sequence of numbers\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 12\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0mcoeffs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcoeffs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mTypeError\u001b[0m: Argument should be a sequence of numbers" - ] - } - ], - "source": [ - "Polynomial([3, 'a', 5])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Debugging\n", - "\n", - "While we're on the subject of errors, we should talk a little bit about how to root out those bugs. One way that can be quite fruitful is simply heavy use of the print() function, telling Python to print various bits of informations as your program is running so you can spot where something has gone wrong. You can then \"comment out\" or delete the print() functions when you are done with them (and you probably should, since while printing might not seem like much it can slow a program down a surprising amount!).\n", - "\n", - "Python provides a module that allows you to walk through your program step by step to see how it is working. Just import the module pdb, and you can get started.\n", - "\n", - "Firstly, it's good not to have to debug your program from the start, but to choose a problematic part of the program to interrogate. Just add pdb.set_trace() before the bit of code you wish to examine.\n", - "\n", - "Now when you run your code, you can interact with it as it is executing using simple commands. The first to know is that q is quit.\n", - "\n", - "To advance through your program, you have two main options, step and next, which can be abbreviated as s or n. The difference is s will go \"inside\" a function on a line, but n will simply evaluate the function and move on to the next line. This distinction is not really clear from the names, so I like to imagine that s stands for \"sub-routine\", which is another word for \"function\" in computer programming. To skip ahead to the end of a function you are currently \"inside\", type r, which stands for return.\n", - "\n", - "So, great, we can move through the lines of our program step by step. But what does this really tell us? Well, the great thing is, we can actually run any line of code or print any variable while we're inside. To run a line of code (for instance, to change a variable manually to see what happens), just type that line in, or prefix the line with a ! if there is any risk of ambiguity. To print a variable inside the debugger, you can just type p variable_name, to save you typing print() every time. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "### EXAMPLE VIDEO TO GO HERE" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.1" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/PurePy 12. Parallel Computing/.ipynb_checkpoints/12.0 Parallel Computing-checkpoint.ipynb b/PurePy 12. Parallel Computing/.ipynb_checkpoints/12.0 Parallel Computing-checkpoint.ipynb deleted file mode 100644 index 2fd6442..0000000 --- a/PurePy 12. Parallel Computing/.ipynb_checkpoints/12.0 Parallel Computing-checkpoint.ipynb +++ /dev/null @@ -1,6 +0,0 @@ -{ - "cells": [], - "metadata": {}, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/PurePy 2. Logic and Flow/.ipynb_checkpoints/2.0 Logic and Flow-checkpoint.ipynb b/PurePy 2. Logic and Flow/.ipynb_checkpoints/2.0 Logic and Flow-checkpoint.ipynb deleted file mode 100644 index 82339db..0000000 --- a/PurePy 2. Logic and Flow/.ipynb_checkpoints/2.0 Logic and Flow-checkpoint.ipynb +++ /dev/null @@ -1,894 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![title](../header.png)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Logic and flow control\n", - "\n", - "When programming, it is rare that our programs are so simple that they are merely a list of instructions. Often, we are required to perform an operation several times (with slight modification), or make a decision as to whether to perform one operation or another. These require the related notions of logic, and flow control.\n", - "\n", - "## Booleans\n", - "\n", - "So far we have met numbers, and briefly strings, as basic types of data in Python. We now introduce the so-called boolean types, named for the English mathematician George Boole. These are the basic atoms of logical reasoning: the condition of being True or False." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "this_is_true = True\n", - "this_is_false = False" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pay close attention. These capitalized True and False words are neither strings, nor variables. They are examples of the special keywords that Python form part of the Python language, which we are not allowed to use as variables.\n", - "\n", - "Of course, we do not want to have to manually assign things to being True or False. We wish to have the computer do it for us! This is where logical expressions come in. If mathematical expressions evaluate to a number, then logical expressions evaluate to a boolean.\n", - "\n", - "Firstly, operations with booleans. There are 3 basic operations we can use to combine booleans to give a new boolean. The simplest, is \"not\". Applying the \"not\" operation to a boolean reverses its value:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(not True)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(not not True)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(not False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(not(False)) # you can use brackets in boolean expressions\n", - " #like in mathematical expressions,\n", - " # to make them easier to read" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next operation is called \"or\". \"Or\" takes two booleans, and is considered True if either of its input booleans are True. You can think of it as \"one, the other, or both\"." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(True or False)" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(True or True)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(False or False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The final operation is \"and\". \"And\" is considered True only if both inputs are True:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(True and True)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(True and False)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(False and False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that and, or, not are all keywords.\n", - "\n", - "Now, this may seem all very abstract. The real use of these logical operations is that the inputs can be replaced by other logical expressions, which are evaluated before being fed into the logical operation. Most of these other logical expressions will be comparisons between objects. Suppose I am writing a quiz application. When the player gives an answer, I must make a comparison between the answer they give, and the correct answer, to decide whether or not they score a point. Two simple kinds of comparison are the greater than/less than comparisons between numbers: " - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "x = 5\n", - "print(x < 6)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(x < 3)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(x > 2 and x < 7)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(x < 1 or x < 9)" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(x >= 6) # greater than or equal!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To make a direct comparison for equality, we use a double equals ==, to distinguish it from the variable assignment symbol =:" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(x == 5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To check whether two things are not equal, use !=" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(x != 5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can use the modulo (\"remainder\") operator to check whether a number is, say, even:" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(x % 2 == 0) # no remainder when divided by 2 means it is even" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You may be surprised to find it is possible to compare lots of things, not just numbers. For example:" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(\"cat\" < \"dog\") # because cat comes first in the dictionary!" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(\"cat\" != \"Cat\") # capitals matter!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that we are thoroughly bored of booleans, let's put them to work by using them to control our code.\n", - "\n", - "## if-statements\n", - "\n", - "Now we start programming proper. Using if-statements, we can tell our program to do something only if a particular expression is True. For example:" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "What is the capital of France? Paris\n", - "Correct!\n" - ] - } - ], - "source": [ - "answer = input(\"What is the capital of France? \")\n", - "if answer == \"Paris\" or answer == \"paris\":\n", - " print(\"Correct!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The key part for us, of course, is the second and third line. Firstly, the second line. It's what is called an if-statement, and it announces its arrival with the keyword \"if\". Following \"if\" is a boolean expression, of the kind we have looked at above. Finally, there is a colon.\n", - "\n", - "A colon at the end of a line in Python announces that we are starting a new block of code, and the line is called the header of the block. In the case of the if-statement, the block is all the code that should be executed, should the if statement evaluate to True. Following every header, the next line should be indented by 4 spaces. The use of indentation is quite perculiar to Python; other languages tend to use curly braces to denote code blocks.\n", - "\n", - "Every line following the if-statement that is indented will be executed only if the boolean expression comes out True. To end the code block, and resume the normal flow of the program, begin a line without indentation. Example:" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Can confirm that 5 is greater than 3,\n", - "Please carry on with your day\n", - "\n", - "The if-statement has ended now\n", - "\n", - "The second if-statement has ended now\n" - ] - } - ], - "source": [ - "if 5 > 3:\n", - " print(\"Can confirm that 5 is greater than 3,\")\n", - " print(\"Please carry on with your day\")\n", - "\n", - "print(\"\")\n", - "print(\"The if-statement has ended now\")\n", - "print(\"\")\n", - "\n", - "if 2 > 3:\n", - " print(\"It seems that mathematics has ceased to function, as 2 is now greater than 3,\")\n", - " print(\"If you are seeing this output, be very alarmed\")\n", - " \n", - "print(\"The second if-statement has ended now\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From now on, we will be encountering indentation a lot. The structure of a Python program is expressed using indentation, and the Python interpreter can be very picky about correct indentation. So pay attention: always indent after a header!\n", - "\n", - "Now, it seems reasonable that if we wish to execute some code if something is True, there should be an option to do something only if it fails to be True. For this, we turn to else." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "What is the capital of France? Moscow\n", - "Incorrect\n" - ] - } - ], - "source": [ - "answer = input(\"What is the capital of France? \")\n", - "if answer == \"Paris\" or answer == \"paris\":\n", - " print(\"Correct!\")\n", - "else:\n", - " print(\"Incorrect\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Hence, an if-else statement is like a fork in the road for the program. Now, if we want to set lots of little forks in the road, it might be tempting to do this:" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "What is the capital of France? F\n", - "Very Funny\n" - ] - } - ], - "source": [ - "answer = input(\"What is the capital of France? \")\n", - "if answer == \"Paris\" or answer == \"paris\":\n", - " print(\"Correct!\")\n", - "else:\n", - " if answer == \"F\":\n", - " print(\"Very Funny\")\n", - " else:\n", - " print(\"Incorrect!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Read this example to ensure that you understand it, and then forget about it. Python has a neater solution, rolling the else: if... part into a single line:" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "What is the capital of France? F\n", - "Very Funny\n" - ] - } - ], - "source": [ - "answer = input(\"What is the capital of France? \")\n", - "if answer == \"Paris\" or answer == \"paris\":\n", - " print(\"Correct!\")\n", - "elif answer == \"F\": # elif is short for \"else, if\"\n", - " print(\"Very Funny\")\n", - "else:\n", - " print(\"Incorrect!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this way, you can set a whole chain of conditions to check for before doing the else block. That's pretty much all there is to if-statements. It is worth bearing in mind, however, that if your program is becoming a tangled mess of if, elif, else, with varying layers of depth of indentation, it's probably time to rethink your design. For example, we will soon meet a structure called a dictionary, which would allow us to store the possible answers to the quiz question alongside their responses from the program in a table." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Flow control: for-loops\n", - "\n", - "There are two kinds of loop in Python. A loop is a section of code that is repeated several times, usually with some variation.\n", - "\n", - "A for-loop is a loop that completes a task a certain number of times. In most programming languages, you simply specify \"do this 10 times\". In Python, you must \"iterate over\" something. Precisely what that means will be discussed in the more advanced articles. However, the intuition is straightforward enough: we specify some kind of sequence, and perform a task for each term in the sequence.\n", - "\n", - "Here is an example:" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "H\n", - "e\n", - "l\n", - "l\n", - "o\n", - " \n", - "w\n", - "o\n", - "r\n", - "l\n", - "d\n", - "!\n" - ] - } - ], - "source": [ - "for letter in \"Hello world!\":\n", - " print(letter)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's unpack it. Again, we have that pattern of keyword -- this time \"for\" -- followed by a statement and ending in a colon, all followed by an indented block. The indented block is the section of code that is to be repeated.\n", - "\n", - "Now, \"Hello world!\" is acting as the sequence -- it is a sequence of characters. What about a list of words?" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello\n", - "World\n" - ] - } - ], - "source": [ - "for word in [\"Hello\", \"World\"]:\n", - " print(word)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The sequence here is a list, denoted by square braces (we'll see much more of lists in tutorials to come!). In the last two examples, \"letter\" and \"word\" are temporary variables we assign to each member of the list as we iterate through it. They can be anything -- letter and word were just chosen here to be clear and readable.\n", - "\n", - "The design philosophy here is that, when programming, if we want to do a task over and over again, we probably want to take a collection of data, such as a list, and perform an operation on each piece of data. That is what this is all about.\n", - "\n", - "Now, what if we really do want to do something 10 times, rather than work our way through a word or list? Then we have a function called range() which generates a sequences of numbers for us. Want to do something 10 times?" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n" - ] - } - ], - "source": [ - "for x in range(10):\n", - " print(\"Spam\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note, we still had to specify a dummy variable x, but we didn't have to mention it in the code block. We just performed the task for each element of the sequence provided by the range() function which is" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n", - "1\n", - "2\n", - "3\n", - "4\n", - "5\n", - "6\n", - "7\n", - "8\n", - "9\n" - ] - } - ], - "source": [ - "for x in range(10):\n", - " print(x)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## While-loops\n", - "\n", - "The other kind of loop we have at our disposal is called a while-loop. Instead of doing something a fixed number of times, the while-loop executes its contents until some condition is met. This makes them work a lot like if statements, since we are checking whether a certain logical expression evaluates to True, or False.\n", - "\n", - "While-loops come with a word of warning. Prudence is required when programming the loop. If the condition is never met, then the program may continue to execute forever, until it is halted by outside forces, such as an interrupt message from the keyboard (usually ctrl+c), or the computer freezes because the computations it is performing have got out of hand.\n", - "\n", - "As a familiar real-world example, a computer game is nothing else but a while-loop. The loop consists of getting input from the player via the keyboard or joypad, updating the game state, and then drawing the results on the screen. This loop is repeated possibly hundreds of times per second in the case of real-time games, or at the leisure of the player in turn-based games. The loop halts when the player wins, loses, or quits the game.\n", - "\n", - "The first example we will see for a while-loop is one that emulates a for-loop. In this case, a certain counter is started, and that counter is incremented each time the looping block is executed. When the counter reaches a certain point, the loop stops.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n" - ] - } - ], - "source": [ - "counter = 0\n", - "while counter < 10:\n", - " print(\"Spam\")\n", - " counter = counter + 1 # increment the counter" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Of course, there is not much point in doing this. However, counters remain useful if they only increment under specific conditions, which requires use of an if-statement to decide when to increment the counter." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## The fizzbuzz challenge\n", - "\n", - "This is a classic programming exercise, appearing in many courses and even job interviews. The task is simple, but if you can solve it, you know you've got the hang of logic and flow control. Your task is to write a short program that prints out the numbers 1 to 100, but if the number is divisible by 3, to print \"Fizz\" instead; and if it is divisible by 5, print \"Buzz\"; and if it is divisible by both 3 and 5, print \"Fizzbuzz\". Everything you need to solve this challenge is contained in the above text, but you will need to design an algorithm that successfully combines these elements to produce the correct solution.\n", - "\n", - "Have a good go, but if you get stuck, see the video below for a solution:" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [ - { - "data": { - "image/jpeg": "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\n", - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 32, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from IPython.display import YouTubeVideo\n", - "YouTubeVideo(\"CzPpVurUSIM\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.2" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/PurePy 2. Logic and Flow/.ipynb_checkpoints/logic and flow-checkpoint.ipynb b/PurePy 2. Logic and Flow/.ipynb_checkpoints/logic and flow-checkpoint.ipynb deleted file mode 100644 index cf5b1a3..0000000 --- a/PurePy 2. Logic and Flow/.ipynb_checkpoints/logic and flow-checkpoint.ipynb +++ /dev/null @@ -1,898 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![title](../header.png)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Logic and flow control\n", - "\n", - "When programming, it is rare that our programs are so simple that they are merely a list of instructions. Often, we are required to perform an operation several times (with slight modification), or make a decision as to whether to perform one operation or another. These require the related notions of logic, and flow control.\n", - "\n", - "## Booleans\n", - "\n", - "So far we have met numbers, and briefly strings, as basic types of data in Python. We now introduce the so-called boolean types, named for the English mathematician George Boole. These are the basic atoms of logical reasoning: the condition of being True or False." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "this_is_true = True\n", - "this_is_false = False" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Pay close attention. These capitalized True and False words are neither strings, nor variables. They are examples of the special keywords that Python form part of the Python language, which we are not allowed to use as variables.\n", - "\n", - "Of course, we do not want to have to manually assign things to being True or False. We wish to have the computer do it for us! This is where logical expressions come in. If mathematical expressions evaluate to a number, then logical expressions evaluate to a boolean.\n", - "\n", - "Firstly, operations with booleans. There are 3 basic operations we can use to combine booleans to give a new boolean. The simplest, is \"not\". Applying the \"not\" operation to a boolean reverses its value:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(not True)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(not not True)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(not False)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(not(False)) # you can use brackets in boolean expressions\n", - " #like in mathematical expressions,\n", - " # to make them easier to read" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next operation is called \"or\". \"Or\" takes two booleans, and is considered True if either of its input booleans are True. You can think of it as \"one, the other, or both\"." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(True or False)" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(True or True)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(False or False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The final operation is \"and\". \"And\" is considered True only if both inputs are True:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(True and True)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(True and False)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(False and False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that and, or, not are all keywords.\n", - "\n", - "Now, this may seem all very abstract. The real use of these logical operations is that the inputs can be replaced by other logical expressions, which are evaluated before being fed into the logical operation. Most of these other logical expressions will be comparisons between objects. Suppose I am writing a quiz application. When the player gives an answer, I must make a comparison between the answer they give, and the correct answer, to decide whether or not they score a point. Two simple kinds of comparison are the greater than/less than comparisons between numbers: " - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "x = 5\n", - "print(x < 6)" - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(x < 3)" - ] - }, - { - "cell_type": "code", - "execution_count": 48, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(x > 2 and x < 7)" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(x < 1 or x < 9)" - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(x >= 6) # greater than or equal!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To make a direct comparison for equality, we use a double equals ==, to distinguish it from the variable assignment symbol =:" - ] - }, - { - "cell_type": "code", - "execution_count": 51, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(x == 5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To check whether two things are not equal, use !=" - ] - }, - { - "cell_type": "code", - "execution_count": 52, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(x != 5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can use the modulo (\"remainder\") operator to check whether a number is, say, even:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'x' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;36m2\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# no remainder when divided by 2 means it is even\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mNameError\u001b[0m: name 'x' is not defined" - ] - } - ], - "source": [ - "print(x % 2 == 0) # no remainder when divided by 2 means it is even" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You may be surprised to find it is possible to compare lots of things, not just numbers. For example:" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(\"cat\" < \"dog\") # because cat comes first in the dictionary!" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(\"cat\" != \"Cat\") # capitals matter!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that we are thoroughly bored of booleans, let's put them to work by using them to control our code.\n", - "\n", - "## if-statements\n", - "\n", - "Now we start programming proper. Using if-statements, we can tell our program to do something only if a particular expression is True. For example:" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "What is the capital of France? Paris\n", - "Correct!\n" - ] - } - ], - "source": [ - "answer = input(\"What is the capital of France? \")\n", - "if answer == \"Paris\" or answer == \"paris\":\n", - " print(\"Correct!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The key part for us, of course, is the second and third line. Firstly, the second line. It's what is called an if-statement, and it announces its arrival with the keyword \"if\". Following \"if\" is a boolean expression, of the kind we have looked at above. Finally, there is a colon.\n", - "\n", - "A colon at the end of a line in Python announces that we are starting a new block of code, and the line is called the header of the block. In the case of the if-statement, the block is all the code that should be executed, should the if statement evaluate to True. Following every header, the next line should be indented by 4 spaces. The use of indentation is quite perculiar to Python; other languages tend to use curly braces to denote code blocks.\n", - "\n", - "Every line following the if-statement that is indented will be executed only if the boolean expression comes out True. To end the code block, and resume the normal flow of the program, begin a line without indentation. Example:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Can confirm that 5 is greater than 3,\n", - "Please carry on with your day\n", - "\n", - "The if-statement has ended now\n", - "\n", - "The second if-statement has ended now\n" - ] - } - ], - "source": [ - "if 5 > 3:\n", - " print(\"Can confirm that 5 is greater than 3,\")\n", - " print(\"Please carry on with your day\")\n", - "\n", - "print(\"\")\n", - "print(\"The if-statement has ended now\")\n", - "print(\"\")\n", - "\n", - "if 2 > 3:\n", - " print(\"It seems that mathematics has ceased to function, as 2 is now greater than 3,\")\n", - " print(\"If you are seeing this output, be very alarmed\")\n", - " \n", - "print(\"The second if-statement has ended now\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From now on, we will be encountering indentation a lot. The structure of a Python program is expressed using indentation, and the Python interpreter can be very picky about correct indentation. So pay attention: always indent after a header!\n", - "\n", - "Now, it seems reasonable that if we wish to execute some code if something is True, there should be an option to do something only if it fails to be True. For this, we turn to else." - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "What is the capital of France? Moscow\n", - "Incorrect\n" - ] - } - ], - "source": [ - "answer = input(\"What is the capital of France? \")\n", - "if answer == \"Paris\" or answer == \"paris\":\n", - " print(\"Correct!\")\n", - "else:\n", - " print(\"Incorrect\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Hence, an if-else statement is like a fork in the road for the program. Now, if we want to set lots of little forks in the road, it might be tempting to do this:" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "What is the capital of France? F\n", - "Very Funny\n" - ] - } - ], - "source": [ - "answer = input(\"What is the capital of France? \")\n", - "if answer == \"Paris\" or answer == \"paris\":\n", - " print(\"Correct!\")\n", - "else:\n", - " if answer == \"F\":\n", - " print(\"Very Funny\")\n", - " else:\n", - " print(\"Incorrect!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Read this example to ensure that you understand it, and then forget about it. Python has a neater solution, rolling the else: if... part into a single line:" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "What is the capital of France? London\n", - "Incorrect!\n" - ] - } - ], - "source": [ - "answer = input(\"What is the capital of France? \")\n", - "if answer == \"Paris\" or answer == \"paris\":\n", - " print(\"Correct!\")\n", - "elif answer == \"F\": # elif is short for \"else, if\"\n", - " print(\"Very Funny\")\n", - "else:\n", - " print(\"Incorrect!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this way, you can set a whole chain of conditions to check for before doing the else block. That's pretty much all there is to if-statements. It is worth bearing in mind, however, that if your program is becoming a tangled mess of if, elif, else, with varying layers of depth of indentation, it's probably time to rethink your design. For example, we will soon meet a structure called a dictionary, which would allow us to store the possible answers to the quiz question alongside their responses from the program in a table." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Flow control: for-loops\n", - "\n", - "There are two kinds of loop in Python. A loop is a section of code that is repeated several times, usually with some variation.\n", - "\n", - "A for-loop is a loop that completes a task a certain number of times. In most programming languages, you simply specify \"do this 10 times\". In Python, you must \"iterate over\" something. Precisely what that means will be discussed in the more advanced articles. However, the intuition is straightforward enough: we specify some kind of sequence, and perform a task for each term in the sequence.\n", - "\n", - "Here is an example:" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "H\n", - "e\n", - "l\n", - "l\n", - "o\n", - " \n", - "w\n", - "o\n", - "r\n", - "l\n", - "d\n", - "!\n" - ] - } - ], - "source": [ - "for letter in \"Hello world!\":\n", - " print(letter)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's unpack it. Again, we have that pattern of keyword -- this time \"for\" -- followed by a statement and ending in a colon, all followed by an indented block. The indented block is the section of code that is to be repeated.\n", - "\n", - "Now, \"Hello world!\" is acting as the sequence -- it is a sequence of characters. What about a list of words?" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello\n", - "World\n" - ] - } - ], - "source": [ - "for word in [\"Hello\", \"World\"]:\n", - " print(word)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The sequence here is a list, denoted by square braces (we'll see much more of lists in tutorials to come!). In the last two examples, \"letter\" and \"word\" are temporary variables we assign to each member of the list as we iterate through it. They can be anything -- letter and word were just chosen here to be clear and readable.\n", - "\n", - "The design philosophy here is that, when programming, if we want to do a task over and over again, we probably want to take a collection of data, such as a list, and perform an operation on each piece of data. That is what this is all about.\n", - "\n", - "Now, what if we really do want to do something 10 times, rather than work our way through a word or list? Then we have a function called range() which generates a sequences of numbers for us. Want to do something 10 times?" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n" - ] - } - ], - "source": [ - "for x in range(10):\n", - " print(\"Spam\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note, we still had to specify a dummy variable x, but we didn't have to mention it in the code block. We just performed the task for each element of the sequence provided by the range() function which is" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n", - "1\n", - "2\n", - "3\n", - "4\n", - "5\n", - "6\n", - "7\n", - "8\n", - "9\n" - ] - } - ], - "source": [ - "for x in range(10):\n", - " print(x)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## While-loops\n", - "\n", - "The other kind of loop we have at our disposal is called a while-loop. Instead of doing something a fixed number of times, the while-loop executes its contents until some condition is met. This makes them work a lot like if statements, since we are checking whether a certain logical expression evaluates to True, or False.\n", - "\n", - "While-loops come with a word of warning. Prudence is required when programming the loop. If the condition is never met, then the program may continue to execute forever, until it is halted by outside forces, such as an interrupt message from the keyboard (usually ctrl+c), or the computer freezes because the computations it is performing have got out of hand.\n", - "\n", - "As a familiar real-world example, a computer game is nothing else but a while-loop. The loop consists of getting input from the player via the keyboard or joypad, updating the game state, and then drawing the results on the screen. This loop is repeated possibly hundreds of times per second in the case of real-time games, or at the leisure of the player in turn-based games. The loop halts when the player wins, loses, or quits the game.\n", - "\n", - "The first example we will see for a while-loop is one that emulates a for-loop. In this case, a certain counter is started, and that counter is incremented each time the looping block is executed. When the counter reaches a certain point, the loop stops.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n", - "Spam\n" - ] - } - ], - "source": [ - "counter = 0\n", - "while counter < 10:\n", - " print(\"Spam\")\n", - " counter = counter + 1 # increment the counter" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Of course, there is not much point in doing this. However, counters remain useful if they only increment under specific conditions, which requires use of an if-statement to decide when to increment the counter." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## The fizzbuzz challenge\n", - "\n", - "This is a classic programming exercise, appearing in many courses and even job interviews. The task is simple, but if you can solve it, you know you've got the hang of logic and flow control. Your task is to write a short program that prints out the numbers 1 to 100, but if the number is divisible by 3, to print \"Fizz\" instead; and if it is divisible by 5, print \"Buzz\"; and if it is divisible by both 3 and 5, print \"Fizzbuzz\". Everything you need to solve this challenge is contained in the above text, but you will need to design an algorithm that successfully combines these elements to produce the correct solution.\n", - "\n", - "Have a good go, but if you get stuck, see the video below for a solution:" - ] - }, - { - "cell_type": "code", - "execution_count": 54, - "metadata": {}, - "outputs": [ - { - "data": { - "image/jpeg": "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\n", - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 54, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from IPython.display import YouTubeVideo\n", - "YouTubeVideo(\"CzPpVurUSIM\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.2" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/PurePy 3. Importing modules/.ipynb_checkpoints/Importing more functions-checkpoint.ipynb b/PurePy 3. Importing modules/.ipynb_checkpoints/Importing more functions-checkpoint.ipynb deleted file mode 100644 index e95d2b3..0000000 --- a/PurePy 3. Importing modules/.ipynb_checkpoints/Importing more functions-checkpoint.ipynb +++ /dev/null @@ -1,275 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Importing More Functions\n", - "\n", - "We have been using just a small handful of functions so far. For our present purposes, a function is a command that takes some inputs, called arguments, and returns an output (this definition will be expanded in the next guide). The function \"evaluates\" to whatever it returns as its output, in the same way that a mathematical expression evaluates to a number, and boolean expression evaluates to True or False. Executing a function is called calling the function. We always know that a function is being called if there is a word followed by opening and closing brackets, which contain the inputs to the function. For example:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "323\n" - ] - } - ], - "source": [ - "a = max(1, 323, 3)\n", - "print(a) # max and print are both functions! the max() function evaluated to 323." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "At time of writing, Python has 68 built-in functions which you can read about here https://docs.python.org/3/library/functions.html. There is no need to memorize this list. As you complete common tasks, your memory for the most useful built-in functions will grow.\n", - "\n", - "There are far more functions available than just these that are built-in. A library is a collection of code that is designed to be used in other programs, to improve the functionality of that program without the programmer having to do it all from scratch. Most programming languages have a \"standard library\", included wherever basic software (such as the interpreter) is installed, and Python is no exception. You can also create your own libraries, and use libraries not included in the standard library. If you installed Python using Anaconda, you will already have access to a large collection of non-standard libraries.\n", - "\n", - "Making use of a library takes the form of importing a module. A module is just a file containing Python code, and the syntax for doing this is easy. Let's import a module from the standard library. Suppose we wish to get some basic statistical facts about a set of data points." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "import statistics" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "That's all there is to it. When a module is imported, the code contained in that module is executed, and any functions, variables, or other objects it provides are loaded into the memory. To access them, we use the dot operator in the following way: modulename.thingwewant. For example, we wish to find the mean in the following data set:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "96.2200289611252\n" - ] - } - ], - "source": [ - "datapoints = [122.4405632654331, 115.75254005489799, 92.53967075824983, 103.53590194401652, 81.27219333775719, 101.61965193699073, 78.30111045299329, 114.11585074905481, 114.76222147968035, 94.74755847301873, 125.01631527683821, 105.17195190259096, 128.33700175849353, 89.38673085168398, 90.40490836715898, 74.35979914723771, 78.9020965751661, 71.23417050705106, 63.745428686885354, 78.75491369730545]\n", - "\n", - "average = statistics.mean(datapoints)\n", - "print(average)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If we anticipate that we will be using the statistics module a lot, we might want to give it a nickname for ease of typing:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "93.64361461563428\n" - ] - } - ], - "source": [ - "import statistics as stats\n", - "med = stats.median(datapoints)\n", - "print(med)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If it is just the case that we want only a small number of the functions provided by a module, we can import just that function. In this case, we no longer have to specify the module that function has been imported from:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "376.7948073834579\n" - ] - } - ], - "source": [ - "from statistics import variance\n", - "var = variance(datapoints) # didn't need to write stats.variance\n", - "print(var)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The Python standard library is large and impressive. Most common tasks computing tasks are aided by standard library modules, such as downloading information from the internet, performing common mathematical operations, reading certain kinds of file from your computer, and so on. You can read about every module available in the standard library in this intimidating list here https://docs.python.org/3/library/." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "## Where does Python import the modules from?\n", - "\n", - "This depends on your Python installation and operating system. With a standard Python installation on a UNIX-like (Mac or Linux) system, there is an environment variable called $PYTHONPATH. On different operating systems, or with an Anaconda installation, this might differ (I think Anaconda just looks inside its own directory although I could be mistaken about this, the documentation isn't clear).\n", - "\n", - "Two places that Python always looks is the current working directory, and the location where the script itself is saved. Recall from the command-line article/video that the user always has a current working directory when navigating using the shell. Whenever Python is running, it also has a current working directory (by default the working directory of the shell from which the script was launched)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Splitting up projects into many files\n", - "\n", - "The other key use of the import command is to allow your work to be spread over multiple files, which can all be brought together by importing them into a \"main\" file. This is essential for making large projects more manageable, as different aspects of the program can be handled independently.\n", - "\n", - "As an amusing anecdote and warning, Mark R Johnson, the sole developer of a game in-progress called Ultima Ratio Regum, had never written a line of code in his life when he started development. The game is staggeringly complex as a first programming project, and happens to be written in Python. While he clearly learned a lot of programming along the way, he missed the tip that programmers tend to split up their code across several files, as well as keeping data files (information the code works on) separated from program files (the actual code). At one point he admitted he was now working from a single Python file several hundred thousand lines long and that as well as being unmanageable from a human psychology perspective was causing his text editor to crash frequently under the strain of such a large file.\n", - "\n", - "So don't be like Mark. If you have to write a large program, split the main parts of the problem up into different files and code them separately. Then import them into a main file. Also, consider if any parts of the program you are writing could be useful in a future program! Then you can put them into one file and just import that file as and when needed in other programs." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "## Modules that can act as libraries or stand-alone programs\n", - "\n", - "There is a useful line of Python that can be used when writing a Python file, to give it a different behaviour if it is run as a stand-alone program, or if it is imported as a module.\n", - "\n", - "As an example, let's suppose I am a physics student who wants to write a very simple module that acts in two possible ways. The module provides some physical constants: if I import the module, I gain access to those physical constants in my other program. Alternatively, if I run the module by itself, say, from the command line, it prints out a list of all the physical constants defined therein.\n", - "\n", - "Here is the example code:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# these constants are available if the module is imported\n", - "speed_of_light = 299792458\n", - "planck = 6.62607004e-34\n", - "electron_charge = -1.6021766208e-19\n", - "electron_mass = 9.10938356e-31\n", - "\n", - "if __name__ == '__main__':\n", - " # this code will ONLY be executed if the module\n", - " # is launched independently, not imported.\n", - " print(\"The speed of light in a vacuum is\", speed_of_light, \"ms⁻ⁱ\")\n", - " print(\"Planck's constant is\", planck, \"J·s\")\n", - " print(\"An electron has charge\", electron_charge, \"C\")\n", - " print(\"An electron has mass\", electron_mass, \"kg\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now if I save this as, say, constants.py, I can import it like so:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Electron rest energy = 8.187105649650028e-14 J\n" - ] - } - ], - "source": [ - "import constants\n", - "\n", - "print(\"Electron rest energy =\",\n", - " constants.electron_mass * constants.speed_of_light**2, \"J\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "However, going to my command line and typing python constants.py displays:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ python constants.py\n", - "The speed of light in a vacuum is 299792458 ms⁻ⁱ\n", - "Planck's constant is 6.62607004e-34 J·s\n", - "An electron has charge -1.6021766208e-19 C\n", - "An electron has mass 9.10938356e-31 kg\n", - "$" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.1" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/PurePy 4. Defining Our Own Functions/.ipynb_checkpoints/Defining our own functions-checkpoint.ipynb b/PurePy 4. Defining Our Own Functions/.ipynb_checkpoints/Defining our own functions-checkpoint.ipynb deleted file mode 100644 index ea228e6..0000000 --- a/PurePy 4. Defining Our Own Functions/.ipynb_checkpoints/Defining our own functions-checkpoint.ipynb +++ /dev/null @@ -1,771 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Defining functions\n", - "\n", - "We have seen that there are many useful functions built-in to Python, and many more available sitting in the standard library and other modules just waiting to be imported to help us complete tasks. This is far from the end of the story though. We previous defined a function to be a command that takes an input argument, and returns an output. The real power of functions, however, is that we can create our own, making a piece of code that can be reused anywhere in our program, or imported into other programs.\n", - "\n", - "Remember, the key to programming is breaking down large complex tasks into small simple tasks. Functions are the key to doing this. They help us to organize and formalize this process by turning each small task into a separate function. These functions can then be reused and combined over and over. For this reason, you should virtually never have to copy and paste code to complete several similar tasks: the correct thing to do is create a function that completes these tasks, and use it several times.\n", - "\n", - "This leads to the concept computer scientists refer to as \"abstraction\". It means that already-solved problems can be essentially forgotten about, treated as single step in an algorithm, however complex that problem may have been initially. For example, if I am building a program that collects stock market data from the web, the simple act of making a webpage request is extraordinarily complex. My request travels in the form of electrical \"on/off\" (0/1) signals through the air to my home router, a computer which reads the metadata of my request and sends the request on a journey via dozens of other routers; to a server with the software to decode my 0s and 1s; which then gets the stock market data by some other magic; and then sends the data back to my computer's address, again via dozens of routers, each one figuring where to send the information next; finally decoded my home computer. The process is extremely complex. But it was solved by the original engineers of the internet and the hyper-text transfer protocol (HTTP) decades ago. To me, in my project, I just run pandas' web data reader function. It's all achieved in a single step. That is abstraction in a nutshell. Functions allow us to solve a complicated problem once, and then treat it as a single step thereafter.\n", - "\n", - "Once again, functions in the code are indicated by a header, followed by the correct indentation. The keyword for the header is def, for \"define\". The function then executes until it reaches the end of the indented text or, more importantly, until it reaches the return keyword, which tells the function what to output." - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def a_silly_function():\n", - " # We are now defining a function\n", - " print(\"This function does nothing\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Defining a function does nothing right away! We have to call it to make the magic happen." - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "This function does nothing\n" - ] - } - ], - "source": [ - "a_silly_function() # a function is executed by typing its name followed by brackets." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The brackets to call the function are very important. If we refer to a function without the brackets, we are just referring to it, not \"activating\" it. For instance, we can set a function to a variable:" - ] - }, - { - "cell_type": "code", - "execution_count": 52, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "silly = a_silly_function" - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "This function does nothing\n" - ] - } - ], - "source": [ - "silly()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Parameters and arguments\n", - "\n", - "As mentioned, functions typically take one or more inputs, making them capable of being used in more situations. Inside the function definition, these inputs are given placeholder names, called parameters, which behave like temporary variables. The parameters are specified in the brackets in the header of the function:" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def says_a_phrase(phrase):\n", - " print('\"' + phrase + ',\" said the computer')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The inputs given to each use of the function are called arguments. Each time the function is executed, the parameters in the function definition are substituted for the arguments provided when the function is called:" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\"Hello,\" said the computer\n", - "\"I think, therefore I am,\" said the computer\n", - "\"But I cannot think, so perhaps I am not,\" said the computer\n" - ] - } - ], - "source": [ - "says_a_phrase(\"Hello\")\n", - "says_a_phrase(\"I think, therefore I am\")\n", - "says_a_phrase(\"But I cannot think, so perhaps I am not\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this example, phrase is the parameter, \"Hello\" and so on are the arguments.\n", - "\n", - "We can provide functions with multiple arguments. There are two ways of doing this: by position, and by keyword. Firstly, by position:" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def says_a_phrase_repeatedly(phrase, repeat):\n", - " for x in range(repeat):\n", - " says_a_phrase(phrase) # notice we are calling the previously defined function inside this function!" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\"Error,\" said the computer\n", - "\"Error,\" said the computer\n", - "\"Error,\" said the computer\n", - "\"Error,\" said the computer\n", - "\"Error,\" said the computer\n" - ] - } - ], - "source": [ - "says_a_phrase_repeatedly(\"Error\", 5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this case, the order of the arguments provided must match the order of the parameters in the definition if the function is to work correctly. The following will not work:" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "'str' object cannot be interpreted as an integer", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0msays_a_phrase_repeatedly\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m5\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"Error\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;32m\u001b[0m in \u001b[0;36msays_a_phrase_repeatedly\u001b[1;34m(phrase, repeat)\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0msays_a_phrase_repeatedly\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mphrase\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mrepeat\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;32mfor\u001b[0m \u001b[0mx\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mrepeat\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 3\u001b[0m \u001b[0msays_a_phrase\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mphrase\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;31m# notice we are calling the previously defined function inside this function!\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;31mTypeError\u001b[0m: 'str' object cannot be interpreted as an integer" - ] - } - ], - "source": [ - "says_a_phrase_repeatedly(5, \"Error\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Positional arguments are useful when there is only a small number of arguments, and the order is easy to remember.\n", - "\n", - "The alternative is keyword arguments. We can use the keyword arguments like so:" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\"0110111,\" said the computer\n", - "\"0110111,\" said the computer\n", - "\"0110111,\" said the computer\n", - "\"0110111,\" said the computer\n", - "\"0110111,\" said the computer\n" - ] - } - ], - "source": [ - "says_a_phrase_repeatedly(phrase=\"0110111\",repeat=5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now the order doesn't matter:" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\"0110111,\" said the computer\n", - "\"0110111,\" said the computer\n", - "\"0110111,\" said the computer\n" - ] - } - ], - "source": [ - "says_a_phrase_repeatedly(repeat=3,phrase=\"0110111\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This is very useful when there are several arguments to pass to a function, and it is not clear in what order these should come. It can also make the meaning of the code clearer when the function is being called. The two approaches of positional and keyword arguments can be combined, so long as we follow the rule that positional arguments come first, followed by keyword arguments." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another useful aspect of keyword arguments is that they can have default values set in the function definition. If the keyword argument is omitted from the function call, the default value is used. This cannot be done with positional arguments, because omitting an argument in this case would change the position of all arguments that follow!" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def says_a_phrase_backwards(phrase, repeat=5):\n", - " for i in range(repeat):\n", - " says_a_phrase(phrase[::-1])" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\"rorre suoireS,\" said the computer\n", - "\"rorre suoireS,\" said the computer\n", - "\"rorre suoireS,\" said the computer\n", - "\"rorre suoireS,\" said the computer\n", - "\"rorre suoireS,\" said the computer\n", - "\"toobeR,\" said the computer\n", - "\"toobeR,\" said the computer\n", - "\"toobeR,\" said the computer\n" - ] - } - ], - "source": [ - "says_a_phrase_backwards(\"Serious error\") # uses default value for repeat\n", - "says_a_phrase_backwards(\"Reboot\", repeat=3) # uses the provided value" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Scope\n", - "\n", - "A key advantage (and source of confusion for beginners) when using functions is the idea of scope of variables.\n", - "\n", - "We are quite used to assigning variables in the main body of our code. These are called global variables. A variable assigned inside of a function block is called a local variable. It has no meaning beyond the boundaries of the function. Once the function has completed its task, the variable is promptly forgotten about.\n", - "\n", - "While this does lead to mistakes and frustration early on, the benefits are roughly twofold. For starters, this means that the same variable name can be reused in different contexts -- we don't always have to come up with something new. Secondly, this makes it much less likely that functions will interfere with one another's inner workings. If functions could easily modify global variables, or the variables local to other functions, we would soon run in to errors. However, if each function is allowed to operate as a self-contained unit, this cannot happen. Example:" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'b' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 6\u001b[0m \u001b[0massigns_some_variables\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 7\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;31mNameError\u001b[0m: name 'b' is not defined" - ] - } - ], - "source": [ - "def assigns_some_variables():\n", - " a = 1\n", - " b = 2\n", - " c = 3\n", - "\n", - "assigns_some_variables()\n", - "print(b)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If, for some reason, we do want a function to set a global variable, we can use the keyword global, like so" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2\n" - ] - } - ], - "source": [ - "def assigns_some_variables():\n", - " global a, b\n", - " a = 1\n", - " b = 2\n", - " c = 3\n", - "\n", - "assigns_some_variables()\n", - "print(b)" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'c' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mc\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;31mNameError\u001b[0m: name 'c' is not defined" - ] - } - ], - "source": [ - "print(c)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If you have to do this too often though, it's likely a sign that your design is flawed in some way. In most larger programs, only a few variables are truly necessary to be global; most variables we set are just stepping stones toward the main results, and should be kept local. You may often here the mantra \"no global variables\". For small scripts performing a single simple task, this is probably overkill, but it's worth bearing in mind for larger projects where conflict and interference between variables becomes more likely." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Returning an output\n", - "\n", - "So far, these functions haven't really given us an output. Rather, they've just been calling the print function, which displays some text to the screen but doesn't actually evaluate to anything, in the sense that a mathematical expression evaluates to a number, or a logical expression evaluates to a boolean.\n", - "\n", - "A return statement is a line in a function that tells the function to stop executing, and output a given value. One function can have several return statements, and which one actually gives the output will depend on flow control. For example:" - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def is_even(n):\n", - " if n % 2 == 0:\n", - " return True\n", - " else:\n", - " return False" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n", - "False\n" - ] - } - ], - "source": [ - "print(is_even(6))\n", - "print(is_even(37))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This output can be used anywhere in your code. For example, it can be set to a variable:" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "parity = is_even(8)\n", - "print(parity)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "or used anywhere else:" - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n", - "2\n", - "4\n", - "6\n", - "8\n" - ] - } - ], - "source": [ - "for x in range(10):\n", - " if is_even(x):\n", - " print(x)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Your functions probably should return a value most of the time. Some programmers don't even consider an outputless function to be a function; instead, they will call it a \"procedure\".\n", - "\n", - "If you want to return more than one output, just seperate the outputs by commas. The output will be given as a tuple, which you can unpack into seperate variables if you like:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "('Foo', 'Bar')\n", - "Foo\n", - "Bar\n" - ] - } - ], - "source": [ - "def two_outputs():\n", - " return \"Foo\", \"Bar\"\n", - "\n", - "print(two_outputs())\n", - "out1, out2 = two_outputs()\n", - "print(out1)\n", - "print(out2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Doc-strings\n", - "\n", - "As your programs get bigger, and especially if you collaborate with others on your program, making it clear what functions do becomes a bigger and bigger problem. Once you have written a function, you, or your collaborators will not necessarily want to have to read the code to remember how to use it. Mostly, they'll just want to know what inputs to give it, and what output to expect -- the computational details may be no longer relevant. For this purpose, we use a doc-string. A doc-string is a short \"help\" paragraph written just below the function's header, delimited by three quote marks. Let's give is_even() a doc-string. There are no hard rules, so long as it is clear." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def is_even(n):\n", - " '''\n", - " Input: an integer\n", - " Ouput: a boolean\n", - " Tells us whether a given integer is even.\n", - " '''\n", - " if n % 2 == 0:\n", - " return True\n", - " else:\n", - " return False" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This snippet can even be accessed \"introspectively\" (that is, a program reading its own source code) like so:" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Help on function is_even in module __main__:\n", - "\n", - "is_even(n)\n", - " Input: an integer\n", - " Ouput: a boolean\n", - " Tells us whether a given integer is even.\n", - "\n" - ] - } - ], - "source": [ - "help(is_even)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Basically all functions in Python and its standard library have doc-strings, and writing good, clear doc-strings should become a habit." - ] - }, - { - "cell_type": "code", - "execution_count": 51, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Help on built-in function max in module builtins:\n", - "\n", - "max(...)\n", - " max(iterable, *[, default=obj, key=func]) -> value\n", - " max(arg1, arg2, *args, *[, key=func]) -> value\n", - " \n", - " With a single iterable argument, return its biggest item. The\n", - " default keyword-only argument specifies an object to return if\n", - " the provided iterable is empty.\n", - " With two or more arguments, return the largest argument.\n", - "\n" - ] - } - ], - "source": [ - "help(max) # example with the max function" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "A function can be given additional annotations, included in its docstring, via the following syntax in the header:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def is_even(n:int) -> bool: # <<< look here\n", - " '''\n", - " Tells us whether a given integer is even.\n", - " '''\n", - " if n % 2 == 0:\n", - " return True\n", - " else:\n", - " return False" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The int and bool words are ignored by Python when running, but make it clear to the programmer what the input and output of the function will be. It then appears in the function's help file:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Help on function is_even in module __main__:\n", - "\n", - "is_even(n:int) -> bool\n", - " Tells us whether a given integer is even.\n", - "\n" - ] - } - ], - "source": [ - "help(is_even)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Worked Example video\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from IPython.display import YouTubeVideo\n", - "YouTubeVideo(\"1WCkAA4B2dE\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.1" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/PurePy 5. Data Structures/.ipynb_checkpoints/5.0 Data Structures-checkpoint.ipynb b/PurePy 5. Data Structures/.ipynb_checkpoints/5.0 Data Structures-checkpoint.ipynb deleted file mode 100644 index 91b7589..0000000 --- a/PurePy 5. Data Structures/.ipynb_checkpoints/5.0 Data Structures-checkpoint.ipynb +++ /dev/null @@ -1,1062 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Data Structures and Comprehensions\n", - "\n", - "Python's data structures are highly flexible and easy to use for a variety of tasks. The basic idea of a data structure to store information in an organized fashion for later use. This tutorial and accompanying video aims to give an overview of the kinds of things Python's data structures can be used for, and how they can be efficiently created out of existing data.\n", - "\n", - "## Basic structures\n", - "\n", - "### Tuple\n", - "\n", - "A tuple is a straightforward way of bundling together a few pieces of related information into an ordered sequence. There is, in general, no expectation that the elements of a tuple be data of the same type. An inventory of products may, for example, be a list of two-element tuples each containing an item (string) and its price (float or integer).\n", - "\n", - "There are 3 main ways to create a tuple. We detail two in this section -- the final will be explained later. The first is the so called \"literal\" creation of a tuple. In this case, we use round brackets to simply group the information, separated by commas:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "a_tuple = (\"hello\", 12345)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The elements of a tuple are accessed by index, starting with the first element indexed as 0:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'hello'" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a_tuple[0]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The other way to create a tuple is with the tuple() built-in function, which will attempt to force another structure to take on the structure of a tuple. Any data ordered sequentially, such as a list or string, is an easy candidate. For instance, we can transform a string into a tuple, each containg a single character like so:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "('h', 'e', 'l', 'l', 'o')" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "tuple(\"hello\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Once we have a tuple, it is very easy to assign each element to a variable. The following syntax will \"unpack\" the tuple we created earlier and set each entry to a different variable:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "word, number = a_tuple" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'hello'" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "word" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "12345" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "number" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another primary use of tuples is in the outputs of functions. A function that returns multiple pieces information is best off returning a tuple containing each item. Then, the function's doc-string (a multi-line comment that appears at the top of the function definition explaining how the function is used) should inform the programmer of what information is returned in the tuple, and in what order. For example, we consider the partition function that can be used on strings. The help() function outputs the function's doc-string:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Help on method_descriptor:\n", - "\n", - "partition(...)\n", - " S.partition(sep) -> (head, sep, tail)\n", - " \n", - " Search for the separator sep in S, and return the part before it,\n", - " the separator itself, and the part after it. If the separator is not\n", - " found, return S and two empty strings.\n", - "\n" - ] - } - ], - "source": [ - "help(str.partition)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It may look a little cryptic, but the second line says that the partition function takes a separator character, here called \"sep\", as its argument, and the output is a tuple containing three pieces of information. Here is an example. Compare the input and output and compare with the doc-string." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "('Cat', ' | ', 'Dog')" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "\"Cat | Dog\".partition(\" | \")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using the previous technique of unpacking, it is very easy to assign each piece of this output to different variables:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "before, middle, after = \"Cat | Dog\".partition(\" | \")" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Cat'" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "before" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Dog'" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "after" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Tuples are an example of an immutable data type. This means that, once created, they cannot be modified. You cannot add or change an entry in a tuple. If you need a tuple to \"change\", then what you must really do is create a new tuple and assign it to the same variable. For instance, let's say I have a pair of numbers (coordinates, say) and wish to add one to each of them. What I must really do is create a new tuple, using the old tuple's information in the process. Example:" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(6, 4)\n" - ] - } - ], - "source": [ - "coordinates = (5, 3)\n", - "# now want new coordinates\n", - "coordinates = (coordinates[0] + 1, coordinates[1] + 1)\n", - "print(coordinates)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### List\n", - "\n", - "Lists are the workhorse structure of Python. Their use case should be pretty intuitive -- you want to make a list of things. While both are order sequentially, they differ from tuples in several important ways. The first is that there is the expectation that the items in the list are all of the same kind. To consider a real world example, imagine you are looking at your receipt after buying groceries. It is perfectly sensible that our receipt is a list of triples (item, quantity, price). However, we would find it incongruous and possibly incomprehensible if items, quantities, and prices were given as separate items in the list! Second, lists are highly dynamic objects. Their entries can be modified, and they can be extended or reduced on the fly. We say they are \"mutable\". Lists have many functions built into them to facilitate these mutations, and we'll showcase some of the more common ones here. Firstly though, we note that creating a list is very similar to creating a tuple. We have 3 methods for doing it, very similar to the tuple, but using square brackets:" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "a_list = [\"One\", \"Two\", \"Three\"]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Also, we have the built-in list() function, which will attempt to turn another data structure into a list. For example, a list can be built from a tuple:" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['Ball', 'Cassidy']" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a_terrible_pair = (\"Ball\", \"Cassidy\") # this is a tuple\n", - "list( a_terrible_pair ) # this is a list!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It is very common to loop over the elements of the list, performing an operation on each element. In the loop syntax, we give each element a temporary name while we work on it. Suppose we wish to print each item in lowercase:" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "one\n", - "two\n", - "three\n" - ] - } - ], - "source": [ - "for number in a_list: # number is the temporary name given to each item as we work on it\n", - " print(number.lower())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "One created, the entries in a list can be modified by simply reassigning that entry using the index:" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['One', 'Zwei', 'Three']\n" - ] - } - ], - "source": [ - "a_list[1] = \"Zwei\"\n", - "print(a_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A very common task is to add entries to the end of the list. We can do this using the append() function that lists can perform. It is worth noting, however, that append() is an efficient solution to an inherently costly operation. When you create a list, the program allocates a certain amount of memory to the list; using the append() method may require the program to allocate more memory to the list, which may involve reorganizing other allocated memory. This increases computing time. Therefore, if it is at all possible, it is best to build your list all in one go, rather than construct it by repeated use of append(). Of course, this is not always possible. Using append() is simple:" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['One', 'Zwei', 'Three', 'Four']\n" - ] - } - ], - "source": [ - "a_list.append(\"Four\")\n", - "print(a_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As well as appending, which always adds the new entry to the end of the list, the insert() function takes as its first argument a position in which to add the new entry:" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['Zero', 'One', 'Zwei', 'Three', 'Four']\n" - ] - } - ], - "source": [ - "a_list.insert(0, \"Zero\")\n", - "print(a_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The syntax for deleting a list element is a bit different. We write it like this:" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['One', 'Zwei', 'Three', 'Four']\n" - ] - } - ], - "source": [ - "del a_list[0]\n", - "print(a_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The final list operation I'd like to show here is pop(). Pop takes an index as its argument, and outputs the element that index refers to. However, it then deletes the element from the list. In this way, we can think of a list as a container, and when we \"pop\" an item from the list, we take it out of the container to do something with it. From our list, we have:" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "THREE\n", - "['One', 'Zwei', 'Four']\n" - ] - } - ], - "source": [ - "an_item = a_list.pop(2)\n", - "print(an_item.upper())\n", - "print(a_list)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using pop() with no argument performs this operation on the last element of the list. This leads to a certain kind of algorithm \"first in, last out\". Conceive of the list as a pile of cards. You can add a card to the top of the stack, or remove the top card. Therefore, the card added first, will be the last card to be retreived.\n", - "\n", - "Let's do an example of this kind of algorithm. Mathematical expressions often use brackets to inform us of the correct order to perform the operations. Suppose we want our program to take a mathematical expression containing brackets, and check that every opening bracket has a corresponding closing bracket, and vice versa. The following code will do this very task:" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "def check_brackets(expression):\n", - " bracket_list = []\n", - " for character in expression:\n", - " if character == \"(\":\n", - " bracket_list.append(character) #add opening brackets to the end of the list\n", - " if character == \")\":\n", - " if len(bracket_list) == 0: \n", - " # the list is empty, so there must be no corresponding opening bracket!\n", - " return False\n", - " else:\n", - " # if there's matching opening bracket, remove it from the list!\n", - " bracket_list.pop()\n", - " \n", - " # returns True only if bracket_list is empty at the end (all brackets were matched)\n", - " return len(bracket_list) == 0 \n", - " \n", - "\n", - "print(check_brackets(\"5 * (6 + (4 - (5 * 6)))\"))\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(check_brackets(\"5 * 5 + ((3+4)\"))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A 2d grid of values can be represented as a list of lists, and values can be looked up by using two indices. A chessboard for a chess game could have the following representation:" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "bP\n" - ] - } - ], - "source": [ - "board = [\n", - " [\"bR\", \"bN\", \"bB\", \"bQ\", \"bK\", \"bB\", \"bN\", \"bR\"],\n", - " [\"bP\", \"bP\", \"bP\", \"bP\", \"bP\", \"bP\", \"bP\", \"bP\"],\n", - " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n", - " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n", - " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n", - " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n", - " [\"wP\", \"wP\", \"wP\", \"wP\", \"wP\", \"wP\", \"wP\", \"wP\"],\n", - " [\"wR\", \"wN\", \"wB\", \"wQ\", \"wK\", \"wB\", \"wN\", \"wR\"]]\n", - "\n", - "# look up what piece is in a square\n", - "print(board[1][3])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Dictionaries\n", - "\n", - "Dictionaries are one of the nicest structures in Python. With our previous structures, we could only retreive elements by index -- that is, by the order in which they appear. However, it is very common that the order is not important to us, and we wish to use a word or other identifier to retreive the item from the structure. This is where dictionaries come in. A dictionary is a \"key-value pair\" -- the key is the word (or other identifier) we use to obtain the value. To create a dictionary, we use curly braces. For example:" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Berlin\n" - ] - } - ], - "source": [ - "capital_cities = {\"UK\": \"London\",\n", - " \"India\": \"New Delhi\",\n", - " \"Germany\": \"Berlin\"}\n", - "print(capital_cities[\"Germany\"])" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "London\n" - ] - } - ], - "source": [ - "beekeeper = {\"Name\": \"Sam\", \"Country\": \"UK\"}\n", - "\n", - "print(capital_cities[beekeeper[\"Country\"]]) # briefly ponder what this line does" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Keys must be immutable -- objects that cannot be changed. Strings and numbers are good examples of immutable data types. Values can be anything you like. Strings, numbers, lists, even functions! Adding an item to a dictionary is as simple as this:" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "capital_cities[\"Russia\"] = \"Moscow\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Dictionaries can be looped over just like lists, but it is usually less clear in what order the items will be looped over, so make sure what you are doing doesn't depend too heavily on the order the operations are performed:" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "UK\n", - "India\n", - "Germany\n", - "Russia\n" - ] - } - ], - "source": [ - "for country in capital_cities:\n", - " print(country)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Deleting an item from a dictionary is akin to doing the same for a list:" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "del capital_cities[\"UK\"]" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'India': 'New Delhi', 'Germany': 'Berlin', 'Russia': 'Moscow'}\n" - ] - } - ], - "source": [ - "print(capital_cities)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So, when do we use a dictionary? A key feature of dictionaries is that they allow us to assign words to other objects. This sounds remeniscent of variables, with which we are already very familiar. The difference is that variables are something created by the programmer to appear in the source code. The keys of a dictionary can be created by the program itself as it is running. Suppose your program is running and creating lots of new data, and you want to assign names to the different bits of data you are creating as the program is running. The program cannot create a new variable. But it can put the data into a dictionary and give it a key!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Exercises with data structures\n", - "\n", - "1. Create a list of 4 tuples, each being a pair containing a \n", - "2. Use the dict() function on the list from exercise 1. Note how this is similar to the tuple() and list() functions. Give the dictionary a name like temp\n", - "3. Create a for-loop that prints the items in the dictionary created in problem 2. Notice how this only prints the keys of the dictionary. Now loop over temp.values() instead of temp, and see what happens. What happens if you loop over temp.items()? What data structures does .items() return?\n", - "4. (challenge) Modify the check_brackets() code above so that it checks the validity of expressions containing a combination of round, square and curly brackets. Hint: Create a dictionary that associates each kind of opening bracket to its appropriate closing bracket (e.g [ to ]).\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Comprehensions\n", - "\n", - "Now we get to something interesting and very useful. So far, we have been constructing tuples, lists and dictionaries by specifying the items individually. This is all very well, but for large structures, it could take forever! A comprehension is a line of code that specifies how to create a structure by describing the objects in it, rather than stating each one explicitly. We will focus here on list comprehensions, but the syntax is very similar for the other structures.\n", - "\n", - "Suppose we wish to create a list containing the numbers 0 to 99. A naive way to achieve this task might be:" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "numbers = []\n", - "for x in range(100):\n", - " numbers.append(x)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As mentioned above, this repeated use of append() is slow -- it would be faster to create the list containing all the numbers at once, rather than constantly modifying the size of the list. This is where list comprehensions come in. The correct syntax, which we will break down in just a moment is:" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "numbers = [x for x in range(100)]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Both of these snippets achieve the same task, but one is shorter, clearer, and faster. Let's take a quick look at the syntax. Note first that we still use square brackets to create the list (if we wanted to use a tuple comprehension, we'd use round brackets). Now, what is this \"x for x\" business? Look first at the latter part of the syntax. It should look exactly like the header of a for-loop for x in range(100). The first x is any expression that should be evaluated for each x before putting the result into the list. In this case, an example really does speak a thousand words:" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364, 3481, 3600, 3721, 3844, 3969, 4096, 4225, 4356, 4489, 4624, 4761, 4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241, 6400, 6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921, 8100, 8281, 8464, 8649, 8836, 9025, 9216, 9409, 9604, 9801]\n" - ] - } - ], - "source": [ - "numbers = [x**2 for x in range(100)]\n", - "print(numbers)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Imagine how long it would have taken to construct this list manually. We have squared each number before adding it to the list. The expression to evaluate can be pretty much anything! For example, we create a list here of tuples containing each number, and whether or not it is prime:" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def is_prime(n):\n", - " '''basic function to determine if a number is prime'''\n", - " if n < 2:\n", - " return False\n", - " for i in range(2, int(n**(0.5)+1)):\n", - " if n % i == 0:\n", - " return False\n", - " return True\n", - "\n", - "prime_list = [(p, is_prime(p)) for p in range(20)] # here's the list comprehension!" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(0, False)\n", - "(1, False)\n", - "(2, True)\n", - "(3, True)\n", - "(4, False)\n", - "(5, True)\n", - "(6, False)\n", - "(7, True)\n", - "(8, False)\n", - "(9, False)\n", - "(10, False)\n", - "(11, True)\n", - "(12, False)\n", - "(13, True)\n", - "(14, False)\n", - "(15, False)\n", - "(16, False)\n", - "(17, True)\n", - "(18, False)\n", - "(19, True)\n" - ] - } - ], - "source": [ - "# Now let's view the list\n", - "for pair in prime_list:\n", - " print(pair)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A list comprehension can also contain if clauses. We could create a list of the prime numbers less than 1000 with the following code:" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]\n" - ] - } - ], - "source": [ - "prime_list = [p for p in range(1000) if is_prime(p)]\n", - "print(prime_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This just about covers the power of list comprehensions. Of course, these have only been toy examples, creating lists of numbers with various properties. List comprehensions can be used to construct lists of pretty much anything. In our demonstration video today, we use list comprehensions to solve a problem that involves extracting data from a file and storing that data in a list.\n", - "\n", - "It is potentially useful when you are just beginning Python, to work always with the Data Structures page from the manual open https://docs.python.org/3/tutorial/datastructures.html. A large amount of what we do when programming is organizing and retrieving data in structures, so having a reference to all the basic tasks Python can do with its structures is extremely useful!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercises with comprehensions\n", - "\n", - "1. Create a list containg the first 10 numbers in the 3 times table, using a comprehension.\n", - "2. Now create a list of 10 lists, with the $k$th list being the first 10 numbers of the $k$ times table, using a list comprehension within a list comprehension (\"nested\").\n", - "3. Head over to https://docs.python.org/3/, the website that contains Python's instruction manual. It's enormous, but knowing your way around it is extremely important for your development as a Python programmer. Try to find the section that explains how to make a dictionary comprehension, and try it out yourself." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "## Example video\n", - "\n", - "In the following example video, we make use of tuples, dictionaries, and list comprehensions to solve a problem." - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [ - { - "data": { - "image/jpeg": "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\nREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERA\nREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQERE\nBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERARE\nQEREBERAREQEREBERAREQEREBERAREQEREH/2Q==\n", - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 36, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from IPython.display import YouTubeVideo\n", - "YouTubeVideo(\"TXiTmmlKmKY\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Footnote to the video\n", - "\n", - "In the video, we implement a counting dictionary. Python's standard library includes an easier and more powerful way to produce a counting dictionary:" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Counter({'B': 2, 'A': 1, 'C': 1})\n" - ] - } - ], - "source": [ - "from collections import Counter\n", - "\n", - "a_list = ['A', 'B', 'B', 'C']\n", - "count = Counter(a_list)\n", - "print(count)" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Most common name is [('John', 60)]\n" - ] - } - ], - "source": [ - "# Hence the same problem from the video can be solved like this:\n", - "\n", - "with open(\"Directory.txt\") as f:\n", - " namecount = Counter([line.partition(\"\\t\")[0] for line in f])\n", - "\n", - "print(\"Most common name is\", namecount.most_common(1))\n", - "# dictionaries provided by Counter come with a function called most_common" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This dictionary comes equipped with some additional features (exactly how this works will be explained in the Object Oriented Programming articles), but the counting algorithm is virtually the same as ours, and seeing algorithms like this is good for the soul of any programmer. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Practice Makes Perfect\n", - "\n", - "Now equipped with a basic knowledge of functions, data structures, mathematical operations and flow control, you are pretty much ready to start using Python to try to solve simple problems. It's now up to you to practice. Not sure about something? Python's documentation and the excellent programming question and answer website stackoverflow.com will almost certainly have the solution.\n", - "\n", - "Not sure where to begin practising? Here's some recommendations:\n", - "\n", - "1) Come up with a simple project of your own to solve.\n", - "\n", - "2) checkio.org is a fantastic website with an enormous selection of Python programming challenges. The objective of each challenge is to write a function in the browser window that completes a certain task, and then the website itself will test if your function really does meet the required criteria. Once you've solved it you can read other people's solutions to get tips on how to do it better.\n", - "\n", - "3) If you enjoy a little mathematics, projecteuler.net is a website that provides mathematical problems that are best solved with the aid of a computer and a programming language such as Python. There are hundreds, and they range from very easy (beginning with a variation on Fizzbuzz!) to obscenely difficult." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.1" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/PurePy 5. Data Structures/.ipynb_checkpoints/datastructures-checkpoint.ipynb b/PurePy 5. Data Structures/.ipynb_checkpoints/datastructures-checkpoint.ipynb deleted file mode 100644 index fc64c44..0000000 --- a/PurePy 5. Data Structures/.ipynb_checkpoints/datastructures-checkpoint.ipynb +++ /dev/null @@ -1,1074 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Data Structures and Comprehensions\n", - "\n", - "Python's data structures are highly flexible and easy to use for a variety of tasks. The basic idea of a data structure to store information in an organized fashion for later use. This tutorial and accompanying video aims to give an overview of the kinds of things Python's data structures can be used for, and how they can be efficiently created out of existing data.\n", - "\n", - "## Basic structures\n", - "\n", - "### Tuple\n", - "\n", - "A tuple is a straightforward way of bundling together a few pieces of related information into an ordered sequence. There is, in general, no expectation that the elements of a tuple be data of the same type. An inventory of products may, for example, be a list of two-element tuples each containing an item (string) and its price (float or integer).\n", - "\n", - "There are 3 main ways to create a tuple. We detail two in this section -- the final will be explained later. The first is the so called \"literal\" creation of a tuple. In this case, we use round brackets to simply group the information, separated by commas:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "a_tuple = (\"hello\", 12345)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The elements of a tuple are accessed by index, starting with the first element indexed as 0:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'hello'" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a_tuple[0]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The other way to create a tuple is with the tuple() built-in function, which will attempt to force another structure to take on the structure of a tuple. Any data ordered sequentially, such as a list or string, is an easy candidate. For instance, we can transform a string into a tuple, each containg a single character like so:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "('h', 'e', 'l', 'l', 'o')" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "tuple(\"hello\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Once we have a tuple, it is very easy to assign each element to a variable. The following syntax will \"unpack\" the tuple we created earlier and set each entry to a different variable:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "word, number = a_tuple" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'hello'" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "word" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "12345" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "number" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another primary use of tuples is in the outputs of functions. A function that returns multiple pieces information is best off returning a tuple containing each item. Then, the function's doc-string (a multi-line comment that appears at the top of the function definition explaining how the function is used) should inform the programmer of what information is returned in the tuple, and in what order. For example, we consider the partition function that can be used on strings. The help() function outputs the function's doc-string:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Help on method_descriptor:\n", - "\n", - "partition(...)\n", - " S.partition(sep) -> (head, sep, tail)\n", - " \n", - " Search for the separator sep in S, and return the part before it,\n", - " the separator itself, and the part after it. If the separator is not\n", - " found, return S and two empty strings.\n", - "\n" - ] - } - ], - "source": [ - "help(str.partition)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It may look a little cryptic, but the second line says that the partition function takes a separator character, here called \"sep\", as its argument, and the output is a tuple containing three pieces of information. Here is an example. Compare the input and output and compare with the doc-string." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "('Cat', ' | ', 'Dog')" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "\"Cat | Dog\".partition(\" | \")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using the previous technique of unpacking, it is very easy to assign each piece of this output to different variables:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "before, middle, after = \"Cat | Dog\".partition(\" | \")" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Cat'" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "before" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Dog'" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "after" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Tuples are an example of an immutable data type. This means that, once created, they cannot be modified. You cannot add or change an entry in a tuple. If you need a tuple to \"change\", then what you must really do is create a new tuple and assign it to the same variable. For instance, let's say I have a pair of numbers (coordinates, say) and wish to add one to each of them. What I must really do is create a new tuple, using the old tuple's information in the process. Example:" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(6, 4)\n" - ] - } - ], - "source": [ - "coordinates = (5, 3)\n", - "# now want new coordinates\n", - "coordinates = (coordinates[0] + 1, coordinates[1] + 1)\n", - "print(coordinates)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### List\n", - "\n", - "Lists are the workhorse structure of Python. Their use case should be pretty intuitive -- you want to make a list of things. While both are order sequentially, they differ from tuples in several important ways. The first is that there is the expectation that the items in the list are all of the same kind. To consider a real world example, imagine you are looking at your receipt after buying groceries. It is perfectly sensible that our receipt is a list of triples (item, quantity, price). However, we would find it incongruous and possibly incomprehensible if items, quantities, and prices were given as separate items in the list! Second, lists are highly dynamic objects. Their entries can be modified, and they can be extended or reduced on the fly. We say they are \"mutable\". Lists have many functions built into them to facilitate these mutations, and we'll showcase some of the more common ones here. Firstly though, we note that creating a list is very similar to creating a tuple. We have 3 methods for doing it, very similar to the tuple, but using square brackets:" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "a_list = [\"One\", \"Two\", \"Three\"]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Also, we have the built-in list() function, which will attempt to turn another data structure into a list. For example, a list can be built from a tuple:" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['Ball', 'Cassidy']" - ] - }, - "execution_count": 33, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a_terrible_pair = (\"Ball\", \"Cassidy\") # this is a tuple\n", - "list( a_terrible_pair ) # this is a list!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It is very common to loop over the elements of the list, performing an operation on each element. In the loop syntax, we give each element a temporary name while we work on it. Suppose we wish to print each item in lowercase:" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "one\n", - "two\n", - "three\n" - ] - } - ], - "source": [ - "for number in a_list: # number is the temporary name given to each item as we work on it\n", - " print(number.lower())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "One created, the entries in a list can be modified by simply reassigning that entry using the index:" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['One', 'Zwei', 'Three']\n" - ] - } - ], - "source": [ - "a_list[1] = \"Zwei\"\n", - "print(a_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A very common task is to add entries to the end of the list. We can do this using the append() function that lists can perform. It is worth noting, however, that append() is an efficient solution to an inherently costly operation. When you create a list, the program allocates a certain amount of memory to the list; using the append() method may require the program to allocate more memory to the list, which may involve reorganizing other allocated memory. This increases computing time. Therefore, if it is at all possible, it is best to build your list all in one go, rather than construct it by repeated use of append(). Of course, this is not always possible. Using append() is simple:" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['One', 'Zwei', 'Three', 'Four']\n" - ] - } - ], - "source": [ - "a_list.append(\"Four\")\n", - "print(a_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As well as appending, which always adds the new entry to the end of the list, the insert() function takes as its first argument a position in which to add the new entry:" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['Zero', 'One', 'Zwei', 'Three', 'Four']\n" - ] - } - ], - "source": [ - "a_list.insert(0, \"Zero\")\n", - "print(a_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The syntax for deleting a list element is a bit different. We write it like this:" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['One', 'Zwei', 'Three', 'Four']\n" - ] - } - ], - "source": [ - "del a_list[0]\n", - "print(a_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The final list operation I'd like to show here is pop(). Pop takes an index as its argument, and outputs the element that index refers to. However, it then deletes the element from the list. In this way, we can think of a list as a container, and when we \"pop\" an item from the list, we take it out of the container to do something with it. From our list, we have:" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "THREE\n", - "['One', 'Zwei', 'Four']\n" - ] - } - ], - "source": [ - "an_item = a_list.pop(2)\n", - "print(an_item.upper())\n", - "print(a_list)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using pop() with no argument performs this operation on the last element of the list. This leads to a certain kind of algorithm \"first in, last out\". Conceive of the list as a pile of cards. You can add a card to the top of the stack, or remove the top card. Therefore, the card added first, will be the last card to be retreived.\n", - "\n", - "Let's do an example of this kind of algorithm. Mathematical expressions often use brackets to inform us of the correct order to perform the operations. Suppose we want our program to take a mathematical expression containing brackets, and check that every opening bracket has a corresponding closing bracket, and vice versa. The following code will do this very task:" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "def check_brackets(expression):\n", - " bracket_list = []\n", - " for character in expression:\n", - " if character == \"(\":\n", - " bracket_list.append(character) #add opening brackets to the end of the list\n", - " if character == \")\":\n", - " if len(bracket_list) == 0: \n", - " # the list is empty, so there must be no corresponding opening bracket!\n", - " return False\n", - " else:\n", - " # if there's matching opening bracket, remove it from the list!\n", - " bracket_list.pop()\n", - " \n", - " # returns True only if bracket_list is empty at the end (all brackets were matched)\n", - " return len(bracket_list) == 0 \n", - " \n", - "\n", - "print(check_brackets(\"5 * (6 + (4 - (5 * 6)))\"))\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(check_brackets(\"5 * 5 + ((3+4)\"))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A 2d grid of values can be represented as a list of lists, and values can be looked up by using two indices. A chessboard for a chess game could have the following representation:" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'bP'" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "board = [\n", - " [\"bR\", \"bN\", \"bB\", \"bQ\", \"bK\", \"bB\", \"bN\", \"bR\"],\n", - " [\"bP\", \"bP\", \"bP\", \"bP\", \"bP\", \"bP\", \"bP\", \"bP\"],\n", - " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n", - " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n", - " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n", - " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n", - " [\"wP\", \"wP\", \"wP\", \"wP\", \"wP\", \"wP\", \"wP\", \"wP\"],\n", - " [\"wR\", \"wN\", \"wB\", \"wQ\", \"wK\", \"wB\", \"wN\", \"wR\"]]\n", - "\n", - "# look up what piece is in a square\n", - "print(board[1][3])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Dictionaries\n", - "\n", - "Dictionaries are one of the nicest structures in Python. With our previous structures, we could only retreive elements by index -- that is, by the order in which they appear. However, it is very common that the order is not important to us, and we wish to use a word or other identifier to retreive the item from the structure. This is where dictionaries come in. A dictionary is a \"key-value pair\" -- the key is the word (or other identifier) we use to obtain the value. To create a dictionary, we use curly braces. For example:" - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Berlin'" - ] - }, - "execution_count": 41, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "capital_cities = {\"UK\": \"London\",\n", - " \"India\": \"New Delhi\",\n", - " \"Germany\": \"Berlin\"}\n", - "print(capital_cities[\"Germany\"])" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'London'" - ] - }, - "execution_count": 43, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "beekeeper = {\"Name\": \"Sam\", \"Country\": \"UK\"}\n", - "\n", - "print(capital_cities[beekeeper[\"Country\"]]) # briefly ponder what this line does" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Keys must be immutable -- objects that cannot be changed. Strings and numbers are good examples of immutable data types. Values can be anything you like. Strings, numbers, lists, even functions! Adding an item to a dictionary is as simple as this:" - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "capital_cities[\"Russia\"] = \"Moscow\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Dictionaries can be looped over just like lists, but it is usually less clear in what order the items will be looped over, so make sure what you are doing doesn't depend too heavily on the order the operations are performed:" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "India\n", - "Russia\n", - "UK\n", - "Germany\n" - ] - } - ], - "source": [ - "for country in capital_cities:\n", - " print(country)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Deleting an item from a dictionary is akin to doing the same for a list:" - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "del capital_cities[\"UK\"]" - ] - }, - { - "cell_type": "code", - "execution_count": 48, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'Germany': 'Berlin', 'India': 'New Delhi', 'Russia': 'Moscow'}" - ] - }, - "execution_count": 48, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "print(capital_cities)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So, when do we use a dictionary? A key feature of dictionaries is that they allow us to assign words to other objects. This sounds remeniscent of variables, with which we are already very familiar. The difference is that variables are something created by the programmer to appear in the source code. The keys of a dictionary can be created by the program itself as it is running. Suppose your program is running and creating lots of new data, and you want to assign names to the different bits of data you are creating as the program is running. The program cannot create a new variable. But it can put the data into a dictionary and give it a key!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Exercises with data structures\n", - "\n", - "1. Create a list of 4 tuples, each being a pair containing a \n", - "2. Use the dict() function on the list from exercise 1. Note how this is similar to the tuple() and list() functions. Give the dictionary a name like temp\n", - "3. Create a for-loop that prints the items in the dictionary created in problem 2. Notice how this only prints the keys of the dictionary. Now loop over temp.values() instead of temp, and see what happens. What happens if you loop over temp.items()? What data structures does .items() return?\n", - "4. (challenge) Modify the check_brackets() code above so that it checks the validity of expressions containing a combination of round, square and curly brackets. Hint: Create a dictionary that associates each kind of opening bracket to its appropriate closing bracket (e.g [ to ]).\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Comprehensions\n", - "\n", - "Now we get to something interesting and very useful. So far, we have been constructing tuples, lists and dictionaries by specifying the items individually. This is all very well, but for large structures, it could take forever! A comprehension is a line of code that specifies how to create a structure by describing the objects in it, rather than stating each one explicitly. We will focus here on list comprehensions, but the syntax is very similar for the other structures.\n", - "\n", - "Suppose we wish to create a list containing the numbers 0 to 99. A naive way to achieve this task might be:" - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "numbers = []\n", - "for x in range(100):\n", - " numbers.append(x)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As mentioned above, this repeated use of append() is slow -- it would be faster to create the list containing all the numbers at once, rather than constantly modifying the size of the list. This is where list comprehensions come in. The correct syntax, which we will break down in just a moment is:" - ] - }, - { - "cell_type": "code", - "execution_count": 51, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "numbers = [x for x in range(100)]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Both of these snippets achieve the same task, but one is shorter, clearer, and faster. Let's take a quick look at the syntax. Note first that we still use square brackets to create the list (if we wanted to use a tuple comprehension, we'd use round brackets). Now, what is this \"x for x\" business? Look first at the latter part of the syntax. It should look exactly like the header of a for-loop for x in range(100). The first x is any expression that should be evaluated for each x before putting the result into the list. In this case, an example really does speak a thousand words:" - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364, 3481, 3600, 3721, 3844, 3969, 4096, 4225, 4356, 4489, 4624, 4761, 4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241, 6400, 6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921, 8100, 8281, 8464, 8649, 8836, 9025, 9216, 9409, 9604, 9801]\n" - ] - } - ], - "source": [ - "numbers = [x**2 for x in range(100)]\n", - "print(numbers)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Imagine how long it would have taken to construct this list manually. We have squared each number before adding it to the list. The expression to evaluate can be pretty much anything! For example, we create a list here of tuples containing each number, and whether or not it is prime:" - ] - }, - { - "cell_type": "code", - "execution_count": 90, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def is_prime(n):\n", - " '''basic function to determine if a number is prime'''\n", - " if n < 2:\n", - " return False\n", - " for i in range(2, int(n**(0.5)+1)):\n", - " if n % i == 0:\n", - " return False\n", - " return True\n", - "\n", - "prime_list = [(p, is_prime(p)) for p in range(20)] # here's the list comprehension!" - ] - }, - { - "cell_type": "code", - "execution_count": 91, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(0, False)\n", - "(1, False)\n", - "(2, True)\n", - "(3, True)\n", - "(4, False)\n", - "(5, True)\n", - "(6, False)\n", - "(7, True)\n", - "(8, False)\n", - "(9, False)\n", - "(10, False)\n", - "(11, True)\n", - "(12, False)\n", - "(13, True)\n", - "(14, False)\n", - "(15, False)\n", - "(16, False)\n", - "(17, True)\n", - "(18, False)\n", - "(19, True)\n" - ] - } - ], - "source": [ - "# Now let's view the list\n", - "for pair in prime_list:\n", - " print(pair)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A list comprehension can also contain if clauses. We could create a list of the prime numbers less than 1000 with the following code:" - ] - }, - { - "cell_type": "code", - "execution_count": 92, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]\n" - ] - } - ], - "source": [ - "prime_list = [p for p in range(1000) if is_prime(p)]\n", - "print(prime_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This just about covers the power of list comprehensions. Of course, these have only been toy examples, creating lists of numbers with various properties. List comprehensions can be used to construct lists of pretty much anything. In our demonstration video today, we use list comprehensions to solve a problem that involves extracting data from a file and storing that data in a list.\n", - "\n", - "It is potentially useful when you are just beginning Python, to work always with the Data Structures page from the manual open https://docs.python.org/3/tutorial/datastructures.html. A large amount of what we do when programming is organizing and retrieving data in structures, so having a reference to all the basic tasks Python can do with its structures is extremely useful!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercises with comprehensions\n", - "\n", - "1. Create a list containg the first 10 numbers in the 3 times table, using a comprehension.\n", - "2. Now create a list of 10 lists, with the $k$th list being the first 10 numbers of the $k$ times table, using a list comprehension within a list comprehension (\"nested\").\n", - "3. Head over to https://docs.python.org/3/, the website that contains Python's instruction manual. It's enormous, but knowing your way around it is extremely important for your development as a Python programmer. Try to find the section that explains how to make a dictionary comprehension, and try it out yourself." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "## Example video\n", - "\n", - "In the following example video, we make use of tuples, dictionaries, and list comprehensions to solve a problem." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "image/jpeg": "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\nREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERA\nREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQERE\nBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERARE\nQEREBERAREQEREBERAREQEREBERAREQEREH/2Q==\n", - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from IPython.display import YouTubeVideo\n", - "YouTubeVideo(\"TXiTmmlKmKY\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Footnote to the video\n", - "\n", - "In the video, we implement a counting dictionary. Python's standard library includes an easier and more powerful way to produce a counting dictionary:" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Counter({'B': 2, 'A': 1, 'C': 1})\n" - ] - } - ], - "source": [ - "from collections import Counter\n", - "\n", - "a_list = ['A', 'B', 'B', 'C']\n", - "count = Counter(a_list)\n", - "print(count)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Most common name is [('John', 60)]\n" - ] - } - ], - "source": [ - "# Hence the same problem from the video can be solved like this:\n", - "\n", - "with open(\"Directory.txt\") as f:\n", - " namecount = Counter([line.partition(\"\\t\")[0] for line in f])\n", - "\n", - "print(\"Most common name is\", namecount.most_common(1))\n", - "# dictionaries provided by Counter come with a function called most_common" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This dictionary comes equipped with some additional features (exactly how this works will be explained in the Object Oriented Programming articles), but the counting algorithm is virtually the same as ours, and seeing algorithms like this is good for the soul of any programmer. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Practice Makes Perfect\n", - "\n", - "Now equipped with a basic knowledge of functions, data structures, mathematical operations and flow control, you are pretty much ready to start using Python to try to solve simple problems. It's now up to you to practice. Not sure about something? Python's documentation and the excellent programming question and answer website stackoverflow.com will almost certainly have the solution.\n", - "\n", - "Not sure where to begin practising? Here's some recommendations:\n", - "\n", - "1) Come up with a simple project of your own to solve.\n", - "\n", - "2) checkio.org is a fantastic website with an enormous selection of Python programming challenges. The objective of each challenge is to write a function in the browser window that completes a certain task, and then the website itself will test if your function really does meet the required criteria. Once you've solved it you can read other people's solutions to get tips on how to do it better.\n", - "\n", - "3) If you enjoy a little mathematics, projecteuler.net is a website that provides mathematical problems that are best solved with the aid of a computer and a programming language such as Python. There are hundreds, and they range from very easy (beginning with a variation on Fizzbuzz!) to obscenely difficult." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.2" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/PurePy 5.5 Command-line interlude/.ipynb_checkpoints/0.2 The command line-checkpoint.ipynb b/PurePy 5.5 Command-line interlude/.ipynb_checkpoints/0.2 The command line-checkpoint.ipynb deleted file mode 100644 index f8fb76c..0000000 --- a/PurePy 5.5 Command-line interlude/.ipynb_checkpoints/0.2 The command line-checkpoint.ipynb +++ /dev/null @@ -1,485 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![header](header0.2.png)\n", - "\n", - "# A very short introduction introduction to command-line computing\n", - "\n", - "This article is not about Python. But it is worth the time of any new Python programmer, or anyone who uses computers a lot. We have to have a discussion about the command-line. Most of us in the modern era have grown up using a graphical user interface (GUI) to interact with our computers. This is where we use a mouse or touch screen to press on-screen buttons, drag-and-drop files, highlight text, move a scroll bar, or bring up a menu. But there is another method, in which we interact with the computer by typing in text commands, and getting text output. For many, this is an ancient relic seen only in films such as The Matrix, War Games, or Hackers, but in the world of computers and computer programming, it remains an invaluable tool.\n", - "\n", - "Now the command-line isn't pretty, and takes a little practice to learn. Most commercial software is no longer written for the command-line for this reason. But as Python beginners, we're generally going to be writing programs that:\n", - "1. Takes some input,\n", - "2. Performs some task or computation,\n", - "3. Gives some output,\n", - "\n", - "rather than writing commercial software. For this purpose, a text-based, command-line is quicker, easier, and just as effective.\n", - "\n", - "Reasons to learn basic command-line skills:\n", - "- Command-line software is easier to write than graphical software.\n", - "- Many tasks easier and faster with the command-line.\n", - "- Access to vast repositories of free command-line software.\n", - "- More freedom to tinker with the workings of your computer.\n", - "- Feel like a hacker.\n", - "\n", - "That said, there are still many tasks which lend themselves better to the graphical interface. I don't know many people, for instance, who manage their emails from the command-line (though such masochists do exist). It's just about choosing the correct tool for the job." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Before we begin, three basic terms. A command-line is any computer interface in which you type text commands rather than click buttons to make things happen. A terminal or terminal emulator is a piece of software on your computer that displays the text for a command-line interface. Finally, a shell is the software \"behind the scenes\", that interprets your commands, performs the tasks you ask of it, and then displays the result in your terminal. These words are sometimes used somewhat interchangeably. Something like \"type this command into the command-line\", \"type this command into the terminal\", \"type this command into the shell\" all mean basically the same thing." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Accessing a command-line\n", - "\n", - "The precise software you use will depend on your operating system. If it is at all possible, you should try to use the Bash shell. This has become the standard shell across Mac OSX and Linux operating systems. It is now also available as an experimental feature of Windows 10: see [here](https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/) for installation instructions. If you are on Windows, but either you do not have Windows 10 or you do not want to install Bash for some reason, then you can use a software that comes with Windows call Powershell. The most basic commands of Powershell and Bash are roughly the same, and most of the things we learn in this tutorial are applicable to Bash and Powershell.\n", - "\n", - "* On Windows, either follow the Bash instructions above, or go to the Start Menu, type Powershell, and open the software it suggests. Note that in Powershell you might have to use backslashes instead of slashes for file paths.\n", - "* On OSX, press cmd+space. This will open the spotlight, which can access any file or program on your computer. Type Terminal, and you will shown the correct software on the menu. Consider adding the terminal to your dock, as it is very useful to have quick access.\n", - "* On Linux systems, go to whatever interface you usually use to open software. If you're on Ubuntu or GNOME or something, try the gnome-terminal, usually accessible just be typing \"Terminal\". If you are on another operating system, you might not have gnome-terminal, but you will definitely have xterm or some equivalent, so try searching for xterm.\n", - "\n", - "Now after allowing everything to load, you should see some kind of command-prompt. On Powershell, I think it will end with a > symbol. In Bash, it will probably be a $ sign. This means the command-line is ready to take commands." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Will I break my computer?\n", - "\n", - "Probably not. There are several checks to make sure you do not do anything dangerous unwittingly. The command for deleting files requires special permissions to delete entire folders, for example. In Bash, many commands that involve installing software, changing important settings or modifying key system files will require you to log-in as an administrator or enter an administrator password before proceeding (even if you are already logged in as an administrator in your normal graphical session).\n", - "\n", - "## Anatomy of a command\n", - "\n", - "A command has the structure \"command options arguments\". The command is a program we'd like to run, or an action we'd like to take. For example, if I open my terminal and simply type firefox, then it opens my web browser. Many commands and programs run inside the terminal, unlike Firefox. Options are things we can add to change the way the command works, often beginning with a - or --, and then a letter or word (for example, it is common in Bash that to get help for using a program, you follow the name of the command with --help e.g firefox --help gives more information about how to use the firefox command). Finally, the arguments are inputs to a command.\n", - "\n", - "As an example, a very simple Bash program called cat can be used to show the contents of a text file in the terminal window. If I just type cat, then the program waits for me to type some text for it to display. If I type cat A_FILE_NAME, then the contents of that file will be displayed: the file name is an argument, an input to the program. Finally, as an example of using it with an option, cat --number A_FILE_NAME. This will display the contents of a file with line numbers shown.\n", - "\n", - "Please see the picture below; the output of the command is not important (I'm just displaying the contents of a file).\n", - "\n", - "![cat](Selection_113.png)\n", - "\n", - "You can usually see what the options are for a program by running PROGRAM_NAME --help or running man PROGRAM_NAME, that is, the program \"manuals\" with the name of the program you want help with as an argument." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## The working directory\n", - "\n", - "The first command we will learn is pwd, which stands for \"print working directory\". The working directory is the folder in your computer that you are currently \"in\", just like on a graphical file browser (My Computer, Finder, nautilus, etc), you are usually viewing and manipulating the contents of just one folder.\n", - "\n", - "For instance, when I open my terminal and type pwd, I have something like:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ pwd\n", - "/home/sam" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This shows us where we currently are in our computer's file system. The natural thing to want to do is to view the contents of the current working directory. Just type ls, which is short for \"list\", if I'm not mistaken. Now you should see the contents of the current directory, possibly with colour coding to show different kinds of file if your terminal emulator is fancy enough." - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ ls\n", - "Desktop Pictures\n", - "Documents Public\n", - "Downloads Templates\n", - "Music Videos" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Cool, so now we are starting to orientate ourselves in our computer. In Bash, there are many useful options for ls. For example, ls -a is \"list all\", which shows hidden files (usually files containing settings for programs, which you will only edit occasionally and otherwise get in the way. Hidden files start with a .). You can use ls -l for a more detailed list with file sizes and such. Options that are of one letter can often be joined into one option, so ls -l -a can be ls -la, which will display a detailed list of all the files in your directory.\n", - "\n", - "If you provide a path to a directory to ls as an argument, it will list the contents of that directory instead:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ ls Documents\n", - "Personal\n", - "Work\n", - "Articles\n", - "Letters" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Changing directory\n", - "\n", - "Now we learn how to navigate. The command cd, when given a directory as an argument, will change the current working directory. Example:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ pwd\n", - "/home/sam\n", - "$ cd Documents\n", - "$ pwd\n", - "/home/sam/Documents" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can go \"up\" a directory by navigating to ..:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ pwd\n", - "/home/sam\n", - "$ cd Documents\n", - "$ pwd\n", - "/home/sam/Documents\n", - "$ cd ..\n", - "$ pwd\n", - "/home/sam" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If you need to refer to a folder or file with spaces in, put the file name in quote marks, for example cd \"My Documents\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Relative and absolute paths\n", - "\n", - "So far, we have used relative file paths. This is where the \"route\" taken to the desired directory or file is relative to the current working directory. In the above example, cd Documents took me to Documents because Documents is contained in the current working directory. If my current working directory were, say, home/sam/Pictures, then to navigate to the Documents directory in one move, I could use cd ../Documents, meaning \"go up one level, and then go to Documents\".\n", - "\n", - "However, I can also use what is called an absolute path. This is an exact address, always referring to the same file or directory regardless of the current working directory. In Mac OSX/Linux, starting a path with / makes it absolute. Hence if I am in the Pictures folder (or indeed ANY folder) and want to go to Documents, I can always type" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ cd /home/sam/Documents\n", - "$ pwd\n", - "/home/sam/Documents" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "On Windows Powershell, you can give an absolute path by starting the path with the drive name, like" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "> cd C:\\Users\\Sam\\Documents" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Making a new directory\n", - "\n", - "The command to make a new directory is mkdir, and the directory name is provided as an argument:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ ls\n", - "Desktop Pictures\n", - "Documents Public\n", - "Downloads Templates\n", - "Music Videos\n", - "$ mkdir python-scripts\n", - "$ ls\n", - "Desktop python-scripts\n", - "Documents Public\n", - "Downloads Templates\n", - "Music Videos\n", - "Pictures " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that I chose to use a - instead of a space in my directory name. As a regular user of the command line, this makes it easier to type as I don't have to remember to put it in quotes this way." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Tab completion\n", - "\n", - "One of the nicest features about modern command-lines is that they often allow tab completion. Pressing the TAB key when partway through a command or file in the current directory will complete the command for you, if there is only one possibility. For example, in my /home/sam directory, typing cd Doc and hitting TAB will complete the command to cd Documents. This allows for much more rapid navigation and manipulation.\n", - "\n", - "## Move, copy, or rename a file\n", - "\n", - "It may surprise you that on the command-line, moving and renaming files are the very same command. It's quite simple really. The mv command takes two arguments: the first, a source file; the second, a target. If the target is a directory, the file is moved to that directory. If the target is not a directory, then the source file is renamed to whatever you set target to. For example, if I have a file called my-file in the home folder, and I wish to move it to Documents, I just type mv my-file Documents. If I want to renamed the file to, say, \"my-file2\", I type. mv my-file my-file2.\n", - "\n", - "The copy command, cp works in basically the same way. Let's say my-file contains some software settings that I want to tinker with without risking breaking anything. I should backup the file so I can restore it if I do something wrong. So, cp my-file my-file-backup will create a copy of that file called my-file-backup." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Delete a file\n", - "\n", - "Delete a file with the command rm, followed by the name of the file relative to the current working directory. If you want to delete a folder, you will have to use rm -r DIRECTORY_NAME. This -r stands for \"recursive\" and means \"delete the contents and the folder\"." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Make a new text file\n", - "\n", - "In bash, you can use the command nano followed by a file name (if it doesn't exist it will be created) to open the nano text editor, an easy-to-use terminal-based text editor. Here you can type a Python file, or any other text file you like. The basic commands are given at the bottom (the ^ sign refers to the ctrl key, so to save (\"write out\") a file is ctrl+O. The text editor has syntax highlighting based on the file name, so ending the file name with .py will enable Python highlighting; in other words, the colours will change to reflect the structure of Python code, if you terminal supports colours.\n", - "\n", - "nano isn't the best text editor out there, but it's quick and easy to use if you just need to slightly modify a file while you browse on the command-line.\n", - "\n", - "![nano](Selection_117.png)\n", - "\n", - "On Windows Powershell, you can use notepad.exe FILENAME to achieve a similar end." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Access Python\n", - "\n", - "Well, now we get to the business end. You know how to navigate through your computer and even write a Python program using nano. If Python is installed correctly, and your shell knows where it is, typing python should open the interactive Python interpreter, a command-line interface with a shell that understands Python commands, rather than Bash or Powershell commands. You should see something like this. The >>> means it is ready to start interpreting Python commands." - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ python\n", - "Python 3.6.1 |Anaconda 4.4.0 (64-bit)| (default, May 11 2017, 13:09:58) \n", - "Type \"copyright\", \"credits\" or \"license\" for more information.\n", - ">>>" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From here, we can type any valid Python code and the program will run it. Since we don't know any Python yet, just test it by asking it \"2 + 2\":" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - ">>> 2 + 2\n", - "4" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can leave by typing exit().\n", - "\n", - "Next we'll learn how to run a Python program that you have already written. Type nano hello.py or notepad.exe hello.py. This has made a new Python file. In the file, write" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "print(\"Hello world!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "and save it (ctrl+O in nano), then exit (ctrl+X in nano). This program, if written correctly, will write \"Hello world!\" on the screen.\n", - "\n", - "Then, when in the working directory in which you saved the file, type:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "$ python hello.py\n", - "Hello world!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Hence, python is the program, and hello.py is the argument provided. Now you know how to run any Python file, even one you have downloaded from the Internet.\n", - "\n", - "### Did you get an error when you typed python, even though you installed it fine?\n", - "\n", - "It means that python is not in your shell's PATH variable. Don't worry. The idea is, when you type a command, it would be very slow (and risky) for the shell to just search your entire computer for some program that command could refer to. Instead, there is a list called PATH of places the shell should look to find programs.\n", - "\n", - "So, to solve this, you must find where you have installed Python, and then tell your computer that it's okay to look here when you give it a command.\n", - "\n", - "If you're using Bash:\n", - "1. Navigate to your home folder. The quick way is cd ~, since ~ always refers to your home folder, for convenience.\n", - "2. You need to edit a file called .bashrc. The ., recall, means it is a hidden file. This is just a file that contains settings for your Bash sessions.\n", - "3. Hence, type nano .bashrc. There might already be a bunch of stuff in here. If you're feeling bored but brave sometime, feel free to back up this file and have a play around to see what happens.\n", - "4. Scroll down to the bottom of the file. Add the line:\n", - "\n", - "\n" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "export PATH=\"/path/to/folder/where/python/is/installed:$PATH\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This just means \"change the PATH variable to '/path/to/where/python/is/installed' followed by whatever the PATH variable was before\". Save the file and exit, then type exit into Bash. Open the terminal again and Python should work.\n", - "\n", - "If you're using Windows Powershell\n", - "\n", - "Type into Powershell\n", - "\n", - "[Environment]::SetEnvironmentVariable(\"Path\", \"$env:Path;C:\\path\\to\\folder\\where\\python\\is\\installed\")\n", - "\n", - "This should solve it.\n", - "\n", - "If neither of these work, I'm afraid you'll have to get your Google-fu on." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Still a bit baffled? Check out the video\n", - "\n", - "All of these basic commands are demonstrated in the video below. You'll see that it's pretty easy once you get going.\n", - "\n", - "\n", - "If you're interested in learning more about how to use Bash and become a command-line expert, there's a great free e-book called The Linux Command Line by William E. Shotts Jr." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from IPython.display import YouTubeVideo\n", - "YouTubeVideo(\"poUKA4pOn7k\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Exercise\n", - "\n", - "From the command line, create a folder in your home directory for \"Python-and-computer-notes\" or something. In here, use the nano text editor to write a short summary of everything you learned here, and save it for future reference." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.1" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/PurePy 6. Strings and Text/.ipynb_checkpoints/6.0 Working with text-checkpoint.ipynb b/PurePy 6. Strings and Text/.ipynb_checkpoints/6.0 Working with text-checkpoint.ipynb deleted file mode 100644 index dcc45f4..0000000 --- a/PurePy 6. Strings and Text/.ipynb_checkpoints/6.0 Working with text-checkpoint.ipynb +++ /dev/null @@ -1,1049 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Strings\n", - "\n", - "String manipulation is widely regarded as one of Python's strong points. These segments of text contain many rich features, and it is straightforward in Python to pull strings apart and re-combine them in interesting ways.\n", - "\n", - "Working with strings is an important skill in Python. For one, reading data into a program will often take the form of a file containing text, and so we must be proficient in extracting the bits we're interested in. Moreover, we are humans. We do not want the computer to merely spit out a list of numbers after performing a calculation; we want our outputs presented in a way that we can actually read.\n", - "\n", - "Strings are an immutable data type. The operations we perform involve forging new strings from old, rather than modifying the original string.\n", - "\n", - "## Slicing and dicing\n", - "\n", - "To get a \"slice\" of a string is similar to getting an item from a list (in fact we can also get slices of lists by the same syntax). However, we specify a start and end index, rather than just an index:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "a piece \n" - ] - } - ], - "source": [ - "a_string = \"This is a piece of string\"\n", - "print(a_string[8:16])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can also leave one end \"open\"" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "This\n", - "is a piece of string\n" - ] - } - ], - "source": [ - "print(a_string[:4])\n", - "print(a_string[5:])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To get the last x letters, we can count backwards with negative numbers:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "string\n" - ] - } - ], - "source": [ - "print(a_string[-6:]) # will get the last 6 letters!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Strings can be concatenated (joined together) using the addition operator:" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hallo Welt\n" - ] - } - ], - "source": [ - "print(\"Hallo \" + \"Welt\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If we wish to use this technique to include, for instance, numbers, then we must first convert the number into a string, as + has a different meaning for strings and numbers." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The year is 2017!\n" - ] - } - ], - "source": [ - "year = 2017\n", - "print(\"The year is \" + str(year) + \"!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "These tools already provide a flexible system for string manipulation. Many of the functions that work on sequence-like data will also work on strings. For instance:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "30\n" - ] - } - ], - "source": [ - "print(len(\"How long is a piece of string?\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['A', ' ', 'l', 'i', 's', 't', ' ', 'o', 'f', ' ', 'l', 'e', 't', 't', 'e', 'r', 's']\n" - ] - } - ], - "source": [ - "print(list(\"A list of letters\"))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Special characters and escape sequences\n", - "\n", - "Certain special characters are represented with a backslash followed by a letter, called an escape sequence. Python considers this pairing to be a single character, even though it looks like two characters on the screen. For example, a new line is represented with \\n." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Split a string\n", - "onto two lines\n" - ] - } - ], - "source": [ - "print(\"Split a string\\nonto two lines\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Escape sequences also allow you to use quotation marks inside a string without Python thinking you are closing the string. Finally, if you actually do want to insert a backslash, then \\\\\\ is the escape sequence to insert a backslash.\n", - "\n", - "A full list of escape sequences can be found here http://www.techpaste.com/2014/06/escape-sequences-python/. Probably you don't know what all of these do. Neither do I. Why not try some out anyway?" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Formatting strings\n", - "\n", - "Many languages, such as C and its derivatives, allow a segment of text to receive inputs using a funny looking syntax in which % signs appear everywhere. Python supports this syntax, and in Python 2 this was the preferred way to modify strings. In Python 3, however, we have the more powerful .format() ability.\n", - "\n", - "Have a good look at this section, as it provides the ideal tools for giving useful, readable outputs. However, string formatting is virtually its own mini-langauge, and is a lot to take in at once. The important thing is to know that Python can do all these things. You can work out the details as and when you need them.\n", - "\n", - "The most basic use of string formatting is to insert data from your program into a string. This can be any data that has a suitable string representation, such as numbers. There are many options for doing this. The first is simply by position:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "As I was going to St. Ives I met a man with 7 wives\n" - ] - } - ], - "source": [ - "destination = \"St. Ives\"\n", - "wivescount = 7\n", - "poem = \"As I was going to {} I met a man with {} wives\".format(destination, wivescount)\n", - "print(poem)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Notice that we have two {}s and provide two arguments to the format function. The order that we provide the arguments is the order that they appear in the text. We can reference the arguments more explicitly by including the position (this is useful if the same argument will appear several times:" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "As I was going to St. Ives I met a man with 7 wives,\n", - "those 7 wives had 7 sacks.\n" - ] - } - ], - "source": [ - "poem = \"\"\"As I was going to {0} I met a man with {1} wives,\n", - "those {1} wives had {1} sacks.\"\"\".format(destination, wivescount) # triple quotes allow multi-line paragraphs\n", - "print(poem)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So here we can see the zero'th argument is referenced once; the one'th argument appears 3 times. If we don't want to worry about position, we can use keyword arguments:" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Those 7 sacks had 7 cats\n" - ] - } - ], - "source": [ - "poem = \"\"\"Those {count} sacks had {count} {animals}\"\"\".format(animals=\"cats\", count=wivescount)\n", - "print(poem)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can supply .format() with any data structure, and access its items in the usual way:" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "kits, cats, sacks and wives, how many going to St. Ives?\n" - ] - } - ], - "source": [ - "travellers = [\"wives\", \"sacks\", \"cats\", \"kits\"]\n", - "# access list items\n", - "poem = \"{0[3]}, {0[2]}, {0[1]} and {0[0]}, how many going to {1}?\".format(travellers, destination)\n", - "print(poem)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - ".format() also provides ways to represent floats and large integers." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "There were 23,455,453,424 travellers to St. Ives\n" - ] - } - ], - "source": [ - "large_int = 23455453424\n", - "print(\"There were {0:,} travellers to {1}\".format(large_int, destination))\n", - "# :, adds comma as thousands separator." - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "That answer is 8370968.388294 times too big!\n", - "That answer is 8370968.39 times too big!\n", - "That answer is 8,370,968.39 times too big!\n" - ] - } - ], - "source": [ - "correct_answer = 2802\n", - "rebuke = \"That answer is {0:f} times too big!\".format(large_int/correct_answer)\n", - "# default (6 decimal places)\n", - "print(rebuke)\n", - "rebuke = \"That answer is {0:.2f} times too big!\".format(large_int/correct_answer)\n", - "print(rebuke)\n", - "# two decimal places\n", - "rebuke = \"That answer is {0:,.2f} times too big!\".format(large_int/correct_answer)\n", - "print(rebuke)\n", - "# two decimal places and comma separators" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Yet another use for string formatting is in aligning text. Text can be left-aligned, right-aligned, or centered. Let's place 3 words on separate lines, with line-width of 30 characters, each with a different alignment:" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "right \n", - " left\n", - " center \n" - ] - } - ], - "source": [ - "print( \"{:<30}\\n{:>30}\\n{:^30}\".format(\"right\", \"left\", \"center\") )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So, this is no more mysterious than \"{}\\n{}\\n{}\", but we use the <, >, ^ characters to show alignment followed by the linewidth." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## More ways to carve up strings\n", - "\n", - "In the Data Structures example video, we met a function called partition() that splits up a string if you provide it with a separator character. There are many many functions on strings that perform similar tasks.\n", - "\n", - "For example, we have splitting and joining, which allow easy conversion from lists to strings and strings to list. A string can be split into indvidual words using the split() function:" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['These', 'words', 'will', 'form', 'a', 'list']\n" - ] - } - ], - "source": [ - "listofwords = \"These words will form a list\".split()\n", - "print(listofwords)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Split also will take an argument to specify a different delimiter.\n", - "\n", - "The counter to this is join(), which acts on the character you wish to use a separator, and takes a list as its arguments. This is a faster algorithm for gluing together a bunch of words than repeated use of the + operator, and it can easily be combined with a list comprehension, too." - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello\n" - ] - } - ], - "source": [ - "# just straight up join, good for making a word\n", - "# we here use join on an empty string to glue the letters directly\n", - "word = \"\".join(['H', 'e', 'l', 'l', 'o'])\n", - "print(word)" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "These words will form a list\n" - ] - } - ], - "source": [ - "# here we use join with spaces to separate, making a sentence\n", - "reunited_words = \" \".join(listofwords)\n", - "print(reunited_words)" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Bread,\n", - "Bananas,\n", - "Beans,\n", - "Beer\n" - ] - } - ], - "source": [ - "# more complicated example. the joining string here is a comma followed by new line\n", - "# we also use a list comprehension to capitalize each item in the list\n", - "\n", - "shopping_list = ['bread', 'bananas', 'beans', 'beer']\n", - "readable_shopping = \",\\n\".join([item.capitalize() for item in shopping_list])\n", - "print(readable_shopping)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Cutting off the beginning or end of a line; the string module\n", - "\n", - "It is somewhat common when working with strings to wish to remove a chunk of text from the beginning or end of a line. As an example, suppose I have copied and pasted a numbered list from the internet, and I wish to remove the numbers. The trouble is, the numbers have different numbers of digits, so I can't just do a straight up slice on each line." - ] - }, - { - "cell_type": "code", - "execution_count": 52, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "best_python_books = \"\"\"1. Dive Into Python 3\n", - "2. Automate The Boring Stuff With Python\n", - "3. Python For Everyone\n", - "4. Python Cookbook, 3rd Ed\n", - "5. Python For Data Analysis\n", - "6. Fluent Python\n", - "7. Violent Python\n", - "8. Think Python\n", - "9. Learn Python The Hard Way\n", - "10. Problem Solving with Algorithms and Data Structures Using Python\n", - "11. Python Crash Course\n", - "\"\"\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The tool that comes to our rescue is .strip(), which takes as its argument a collection of characters as a string. Python will remove those characters from the beginning of a string, until it reaches a character not contained in the argument. If we give it no argument, it just removes whitespace (spaces and tabs). To break the list into separate lines, we'll use .splitlines(), which is like split, but splits at linebreaks." - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['1. Dive Into Python 3', '2. Automate The Boring Stuff With Python', '3. Python For Everyone', '4. Python Cookbook, 3rd Ed', '5. Python For Data Analysis', '6. Fluent Python', '7. Violent Python', '8. Think Python', '9. Learn Python The Hard Way', '10. Problem Solving with Algorithms and Data Structures Using Python', '11. Python Crash Course']\n" - ] - } - ], - "source": [ - "lines = best_python_books.splitlines()\n", - "print(lines)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we need to remove the leading characters. Python provides a useful module called string in its standard library, that contains lots of useful strings, as well as additional functions for working with strings. We want to remove the numbers at the start, so we can say:" - ] - }, - { - "cell_type": "code", - "execution_count": 55, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0123456789\n" - ] - } - ], - "source": [ - "import string # gives us a string containing all the numbers\n", - "print(string.digits)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "While this actually requires more keystrokes than simply writing the numbers \"0123456789\", the string module contains many other collections of characters like this such as punctuation" - ] - }, - { - "cell_type": "code", - "execution_count": 56, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\n" - ] - } - ], - "source": [ - "print(string.punctuation)" - ] - }, - { - "cell_type": "code", - "execution_count": 58, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\n" - ] - } - ], - "source": [ - "print(string.ascii_letters)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "These strings are useful for checking facts about other strings. For example, this snippet will check if there is any punctuation in a string:" - ] - }, - { - "cell_type": "code", - "execution_count": 59, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n", - "True\n" - ] - } - ], - "source": [ - "def has_punc(text):\n", - " import string\n", - " for c in string.punctuation:\n", - " if c in text:\n", - " return True\n", - " return False\n", - "\n", - "print( has_punc(\"Has no punctuation\") )\n", - "print( has_punc(\"Has punctuation.\"))\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Anyway, back to our problem. We want to remove the numbers, full stops and whitespace from the strings in the list. Here we go:" - ] - }, - { - "cell_type": "code", - "execution_count": 64, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Dive Into Python\n", - "Automate The Boring Stuff With Python\n", - "Python For Everyone\n", - "Python Cookbook, 3rd Ed\n", - "Python For Data Analysis\n", - "Fluent Python\n", - "Violent Python\n", - "Think Python\n", - "Learn Python The Hard Way\n", - "Problem Solving with Algorithms and Data Structures Using Python\n", - "Python Crash Course\n" - ] - } - ], - "source": [ - "chars_to_remove = \". \" + string.digits # make a string containing all bad chars\n", - "\n", - "nice_list = [book.strip(chars_to_remove) for book in lines]\n", - "\n", - "readable_list = \"\\n\".join(nice_list)\n", - "\n", - "print(readable_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Clearly, to use strip(), we have to be pretty confident about the format of our data. If I had a book called \"20 Cool Python Programs\" in the list, then the \"20\" part would have been stripped out as well.\n", - "\n", - "## Some quick transformations of strings\n", - "\n", - "The developers of Python kindly include many single word ways to make quick adjustments to strings. We just demonstrate a bunch of them here; their functioning should be self explanatory:\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 68, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Some advanced string theory\n", - "some advanced string theory\n", - "SOME ADVANCED STRING THEORY\n", - "sOME ADVANCED STRING THEORY\n", - "Some Advanced String Theory\n", - "Some basic string theory\n" - ] - } - ], - "source": [ - "my_string = \"Some advanced string theory\"\n", - "\n", - "print(my_string.capitalize())\n", - "print(my_string.lower())\n", - "print(my_string.upper())\n", - "print(my_string.swapcase())\n", - "print(my_string.title())\n", - "print(my_string.replace(\"advanced\", \"basic\"))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can read more about how to use strings here\n", - "https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str\n", - "and about the string module here\n", - "https://docs.python.org/3/library/string.html" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "# Text\n", - "\n", - "You may be looking at the title of this section and thinking \"wait, haven't we just learned all about text?\". And the answer is yes... sort of. We've been learning about how to work with text inside Python. We've just been willy-nilly writing some strings and slicing them up. What we have not talked about, and is unfortunately an important thing to be aware of, is text that is out there in the wild.\n", - "\n", - "## The bad news\n", - "\n", - "Some terminology first. A character is the abstract meaning behind the little squiggles you see on the screen that form text. The squiggles themselves are called \"glyphs\". However, the glyphs cannot be the characters, since in different fonts, the same character can be represented by two very different glyphs. So for instance, the character that is \"the first uppercase letter of the latin alphabet and sounds like 'ey'\" is represented by the glyph \"A\". We don't need to worry about glyphs, since this is determined by the font of our computer, not our program.\n", - "\n", - "When we work with text in Python, we just see the strings as \"a sequence of characters\". This is great, and is exactly how you should think of strings when you manipulate them in Python. Trouble is, computers do not store characters; they store numbers written in binary. This means there is a natural problem of deciding which characters correspond to which numbers.\n", - "\n", - "Probably you've not encountered this problem in any meaningful way before. You may have stumbled across webpages with some missing or incorrect characters. But in your life, you've mostly been working with word processed documents, in a familiar word processor, written using characters native to your language. Or you've been using webpages via web-browsers built by people who understand this problem and have essentially solved it for you.\n", - "\n", - "Back in the days of yore, computer users mostly just shared software around their own universities and workplaces, at the very least within their own country. This means that lots of different character encodings sprang up -- methods for turning the bytes (numbers) in a file into text on the screen. In the UK and US, the common solution was ASCII encoding, which due to our relatively small alphabet meant that each character could be stored in a single byte as a number between 0 and 127.\n", - "\n", - "These days, there is something called the internet, which means that text is now flying all over the world, from the US, which uses only a few characters; to Europe, which uses more because of all the accents; to Greece, Russia, and Middle East, which have different alphabets; to China, which has literally thousands of characters. Also, in the 21st century, there are emojis.\n", - "\n", - "So if you're planning on interacting with text that comes from a source outside of your own computer, you might run into problems.\n", - "\n", - "## Unicode\n", - "\n", - "Unicode is a system for organizing the characters of the world, as well as a set of standards for encoding these characters. In a nutshell, each character is assigned to a unicode \"code point\", usually written in . For instance the letter \"A\" is \"0041\". This is not an encoding, but merely an organization method. At least now we can organize the characters of the world into some kind of coherent structure, a bit like a periodic table of elements but for text. According to Wikipedia, the current version of unicode contains 136,755 characters from 139 writing systems, plus additional symbols that are not from any particular writing system, such as emoji. When you create a string in Python, it is considered to be a sequence of unicode code points.\n", - "\n", - "Note that unicode code points are generally given in hexadecimal. This is simply a way of writing down numbers using 16 symbols instead of the usual ten (or two, in binary), meaning larger numbers can be written using fewer digits. Since we have only ten numerals, letters are used instead; the numerals used in hexadecimal are 0123456789ABCDEF. E is fourteen, F is fifteen. 10 is sixteen, 11 is seventeen, all the way to FF, which is 255 in decimal, and then we start again with 100. This is just a way to shorten long numbers in binary -- each hex digit corresponds to 4 binary digits (bits), meaning that a byte is represented by two hex digits. There's rarely any need to do arithmetic with hex-reperesented numbers, or figure out what the decimal/binary representation is. Just be aware that when you see, say, \"A3\" when discussing a unicode code point, it is actually a number.\n", - "\n", - "There remains the question then of how to encode these characters into bytes. Unicode has several possible standards. The reason for different standards is that European computer users, say, whose languages' characters could be stored in 2 bytes, did not want to have to use additional bytes to store all the Chinese characters they seldom used, for example by allocating 4 bytes per character. By having different encoding systems, we've solved one problem, but it's very not flexible. What about times when we need those occasional Chinese characters? What about emoji?\n", - "\n", - "Then two bright sparks, Ken Thompson and Rob Pike, came up with a new encoding system called UTF-8. In their system the number of bytes per character could vary. The standard ASCII characters, for example, could be stored as 1 byte. Accented characters, 2 bytes. 3 bytes is enough to store all the Chinese characters. Other, uncommon symbols, such as emoji, are relegated to taking up 4 bytes. And all of these can co-exist within the same file. There's no need to switch encoding midway through. In theory, it \"just works\".\n", - "\n", - "There is a price to pay, as with most nice things in life. For a program to search through UTF-8 encoded text now takes longer, because it can't count on each of the characters being the same length (in terms of digits); it has to check each byte separately to see when one character ends and the next begins.\n", - "\n", - "Nonetheless, UTF-8 is now the standard encoding on the web, accounting for 90% of websites. The Python interpreter expects Python files to be written in UTF-8. Python \"just works\" when it reads UTF-8 encoded text.\n", - "\n", - "\n", - "## The good news\n", - "\n", - "Working with these different encodings in Python is actually fairly straightforward for the most part. Your mission when working with text in Python should be to convert it to a string as soon as is possible. In string form, you are working directly with characters -- that is to say, unicode code points, and don't have to worry about what these characters are actually stored as in memory.\n", - "\n", - "The two functions you need are str.encode() and bytes.decode() (where str and bytes are the snippet you want to en-/decode. The argument taken is the name of the encoding to be used, given as a string -- the default encoding is UTF-8." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Sam\n", - "\n" - ] - } - ], - "source": [ - "my_name = \"Sam\"\n", - "my_name_as_bytes = my_name.encode()\n", - "print(type(my_name_as_bytes))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If we print my_name_as_bytes, what do we get?" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "b'Sam'\n" - ] - } - ], - "source": [ - "print(my_name_as_bytes)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It looks the same, but with a little b at the beginning. But it is certainly not the same. These are no longer characters, but representations of sequences of bytes. Confused?\n", - "\n", - "Here is what is going on. There is some good news here, actually: the most commonly used characters in English form part of the ASCII character set, which if we recall stores each character as a number between 0 and 127. One of the clever aspects of UTF-8 encoding is that the encodings for these particular characters are identical to their ASCII encodings. You can open a file written in ASCII using an UTF-8 decoding algorithm and you wouldn't know the difference.\n", - "\n", - "Now, when Python represents a sequence of bytes, rather than give you a sequence of numbers, it represents each byte with an ASCII character, as this is usually easier to interpret. Because the letters of Sam are in the ASCII character set, this is no problem! However, the same cannot be said for another string, for example:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "b'This jacket costs \\xc2\\xa330'\n" - ] - } - ], - "source": [ - "jacket = \"This jacket costs £30\"\n", - "jacket_as_bytes = jacket.encode()\n", - "print(jacket_as_bytes)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can see £ sign has a strange representation, because this character is not ASCII (owing to the fact that ASCII is an American standard, so only the dollar sign is part of the system). \\x just means \"heXadecimal\". In other words, these numbers don't have an ASCII representation, so they are given as their hex values instead, and the \\x makes us aware of this.\n", - "\n", - "However, this is still valid UTF-8 bytes, and a program reading these bytes as UTF-8 can recover the original:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "This jacket costs £30\n" - ] - } - ], - "source": [ - "print(jacket_as_bytes.decode('UTF-8'))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Tada! So what happens if we try to encode the last string as ASCII?" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "ename": "UnicodeEncodeError", - "evalue": "'ascii' codec can't encode character '\\xa3' in position 18: ordinal not in range(128)", - "output_type": "error", - "traceback": [ - "\u001b[0;31m------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mUnicodeEncodeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mjacket\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'ASCII'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mUnicodeEncodeError\u001b[0m: 'ascii' codec can't encode character '\\xa3' in position 18: ordinal not in range(128)" - ] - } - ], - "source": [ - "print(jacket.encode('ASCII'))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We get an error, because the £ sign simply has no corresponding ASCII number.\n", - "\n", - "So, soon we'll be looking at how to open a (text) file in Python. How do we know how to decode the text? In general, sadly, we don't. For files that use one of the unicode encodings, the file may have a so called byte-order mark (BOM) at the beginning containing 2 or 3 bytes which indicate the encoding used (though it also might not -- more information on that here http://codesnipers.com/?q=node/68). Other than that, you may have to use some trial and error. Presuming you have a rough idea of what the file should look like when decoded, you could write a loop that tries some different encodings for you. Finally, included with Anaconda is a library that will attempt to determine the encoding for you. We demonstrate its usage here. Let's first create a string with some non-ASCII characters in:" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "# Here I have taken a paragraph from a French newspaper, containing some accented characters\n", - "french_paragraph = \"Vite, de l'ombre ! Un pic de chaleur est attendu en France mardi, selon les instituts météorologiques, qui tablaient la veille sur des températures allant jusqu'à... 38°C ! «On assiste à une dépression sur le proche Atlantique, décrypte Frédéric Decker, météorologue chez MeteoNews. Celui-ci va avoir un effet de pompe à chaleur en faisant remonter de l'air en provenance d'Espagne et du Maghreb.»\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we will encode it into some different formats:" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [], - "source": [ - "encodings = ['UTF-8', 'UTF-16', 'ISO-8859-1', 'macintosh']\n", - "french_bytes = {}\n", - "for code in encodings:\n", - " french_bytes[code] = french_paragraph.encode(code)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now to see if the library is able to have a good guess at how this paragraph has been encoded:" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}\n", - "Correct answer is UTF-8. chardet's guess is: utf-8\n", - "{'encoding': 'UTF-16', 'confidence': 1.0, 'language': ''}\n", - "Correct answer is UTF-16. chardet's guess is: UTF-16\n", - "{'encoding': 'ISO-8859-1', 'confidence': 0.73, 'language': ''}\n", - "Correct answer is ISO-8859-1. chardet's guess is: ISO-8859-1\n", - "{'encoding': 'Windows-1254', 'confidence': 0.5840197866395126, 'language': 'Turkish'}\n", - "Correct answer is macintosh. chardet's guess is: Windows-1254\n" - ] - } - ], - "source": [ - "import chardet\n", - "\n", - "# the dictionary.items() function gives tuples of key-value pairs\n", - "for truecode, byte_string in french_bytes.items():\n", - " # chardet.detect() will make this library attempt to guess \n", - " guess = chardet.detect(byte_string)['encoding']\n", - " print(chardet.detect(byte_string))\n", - " print(\"Correct answer is {}. chardet's guess is: {}\".format(truecode, guess))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So it managed to correctly guess 3/4 encodings. The moral is that this library can help you out, but you mustn't trust it blindly!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.1" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/PurePy 7. Importing Data/.ipynb_checkpoints/7.1 Opening Files-checkpoint.ipynb b/PurePy 7. Importing Data/.ipynb_checkpoints/7.1 Opening Files-checkpoint.ipynb deleted file mode 100644 index 0a72d6e..0000000 --- a/PurePy 7. Importing Data/.ipynb_checkpoints/7.1 Opening Files-checkpoint.ipynb +++ /dev/null @@ -1,469 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Opening files\n", - "\n", - "When we're writing a program, it's pretty clear that we don't want to always have to type the data we're working with directly into the source code. Rather, we want to get the data from an external source: either the web, or a file on our computer. In this article, we're going to look at how to work with files in Python.\n", - "\n", - "Did you read the article about string manipulation, and in particular, the bit about character encodings? It might be helpful here!\n", - "\n", - "## The open() function and its modes\n", - "\n", - "Python has one built-in function for getting the information out of a file, or writing information to a file. \n", - "\n", - "This is simply the open() function. Its first argument is always a string, which is the path to a file.\n", - "\n", - "If you checked out the lesson on using the command line (and if you haven't you really should!), the way that file paths work should be very familiar. They can be either relative or absolute. Relative to what? Well, Python has a current working directory, just like you do when you are working via the command line. This will default to the current working directory you were in when you ran Python. Finally, in Python you should always use forward slashes in file paths, even if your computer uses backslashes. The open() function is smart and will figure this out for you -- it means the same code can easily open files on different operating systems!\n", - "\n", - "What happens next is dependent on the next argument: the mode. This will determine whether the file should be opened as text or as bytes, and whether you want to read the file or write to the file. We'll deal with these modes now.\n", - "\n", - "The function returns a file object, which you should store as a variable to refer to later (otherwise the file will be opened but you won't be able to access it).\n", - "\n", - "### Read mode, 'r'\n", - "\n", - "This is the mode you need to get the data out of a file as text; it is the default mode when opening. By default, it attempts to decode the file using the default encoding of your computer. For instance, a Windows computer and a Linux machine may have different default encodings. To be safe, it's best to specify the correct encoding by passing the keyword argument encoding. \n", - "\n", - "Let's open a text file and read its contents." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "example_file = open('haiku.txt', 'r', encoding='UTF-8')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What can we do with this file? Well, we can try to extract its contents as a string, using .read()." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "contents = example_file.read()" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "This is a text file,\n", - "UTF-8 encoding.\n", - "It has two line breaks.\n" - ] - } - ], - "source": [ - "print(contents)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What happens if we try to read it again?" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "contents2 = example_file.read()" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], - "source": [ - "print(contents2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Nothing! What happened?\n", - "\n", - "When we read a file, you should imagine it like a tape. Just like a tape, once you have read to the end, you have to \"rewind\" it to read it again. To do this, use .seek()." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# go back to the 0th byte\n", - "example_file.seek(0)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "This is a text file,\n", - "UTF-8 encoding.\n", - "It has two line breaks.\n" - ] - } - ], - "source": [ - "contents3 = example_file.read()\n", - "print(contents3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And... it works again. Be warned though: seek() doesn't count characters! It counts bytes, and if you recall from the lesson on strings and text, UTF-8 uses a variable number of bytes to encode each character. So you can't reliably search around the text file using seek() -- you could end up \"between\" characters.\n", - "\n", - "This is one reason I implored in the strings lesson to convert your text into a Python string as soon as possible! Once it's a string, you're safe! You can forget all about bytes and encodings.\n", - "\n", - "Another nice features of the file object is that if you loop over the file object, you will get each line as a string:" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "THIS IS A TEXT FILE,\n", - "\n", - "UTF-8 ENCODING.\n", - "\n", - "IT HAS TWO LINE BREAKS.\n" - ] - } - ], - "source": [ - "example_file.seek(0)\n", - "for line in example_file:\n", - " print(line.upper())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Why are there line breaks in funny places? This is just because each line contains a newline (\\n) character, and each print() prints to a newline, leading to a doubling up of linebreaks.\n", - "\n", - "There's more good news on this front. Since different operating systems prefer different linebreak characters, the file object provided by open() is kind and clever enough to figure out where the linebreaks should be when you loop over it." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "After opening any file, it is essential to close it when you are done -- ideally as soon as you have extracted the text as a string. If a file is opened by one program, other programs cannot use it. Moreover, if your program crashes unexpectedly and you didn't close the file, it may stay hanging around in memory, clogging up your computer and remaining unavailable." - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "example_file.close()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We'll soon meet a better way of closing files safely.\n", - "\n", - "### Write and append modes; 'w' and 'a'\n", - "\n", - "We now know how to get data from a file. The next task is to put data in, and we have two real choices here. Write mode will delete the contents of a file, ready to be re-written from scratch. Append mode will add to the end of the file. Let's just repeat that: write mode will delete the contents of the file to be written, so make sure you've definitely got the right file, and if in doubt, back it up. If the file does not exist, it will be created." - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "new_file = open('newhaiku.txt', 'w', encoding='UTF-8')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To write into the file, we use .write()" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "60" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "haiku = \"Always remember\\nto consider that new lines\\naren't automatic.\"\n", - "new_file.write(haiku)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's write again and see what happens" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Always remember\n", - "to consider that new lines\n", - "aren't automatic.Always remember\n", - "to consider that new lines\n", - "aren't automatic.\n" - ] - } - ], - "source": [ - "new_file.write(haiku)\n", - "new_file.close()\n", - "file_check = open('newhaiku.txt', 'r', encoding='UTF-8')\n", - "contents = file_check.read()\n", - "print(contents)\n", - "file_check.close()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Unfortunately, it looks like I forgot that new lines aren't automatic. Let's add a correctly line-broken version to the end of this file." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Always remember\n", - "to consider that new lines\n", - "aren't automatic.Always remember\n", - "to consider that new lines\n", - "aren't automatic.\n", - "\n", - "Always remember\n", - "to consider that new lines\n", - "aren't automatic.\n" - ] - } - ], - "source": [ - "haiku_file = open('newhaiku.txt', 'a', encoding='UTF-8') # 'a' for \"append\" mode\n", - "\n", - "haiku_file.write('\\n\\n') # two new lines\n", - "haiku_file.write(haiku)\n", - "haiku_file.close()\n", - "\n", - "file_check = open('newhaiku.txt', 'r', encoding='UTF-8')\n", - "contents = file_check.read()\n", - "print(contents)\n", - "file_check.close()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "That's better.\n", - "\n", - "### Opening/writing things as bytes\n", - "\n", - "We have so far been opening files as text -- the bytes in the file are converted to strings of characters. But there are times when we might want to open the file as bytes. There are two main times we might want to do this.\n", - "\n", - "* The file is not a text file!\n", - "* The file is a text file, but we don't know what the encoding is.\n", - "\n", - "In this latter case, we might want to open it as bytes and then use some method to try to determine the encoding, such as the chardet module from the previous topic. Opening something as bytes is just the same, but you add a b:" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "b\"Always remember\\nto consider that new lines\\naren't automatic.Always remember\\nto consider that new lines\\naren't automatic.\\n\\nAlways remember\\nto consider that new lines\\naren't automatic.\"\n", - "{'encoding': 'ascii', 'confidence': 1.0, 'language': ''}\n" - ] - } - ], - "source": [ - "bytes_file = open('newhaiku.txt', 'rb')\n", - "print(bytes_file.read())\n", - "import chardet\n", - "bytes_file.seek(0)\n", - "print(chardet.detect(bytes_file.read()))\n", - "bytes_file.close()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This incorrect guess from chardet just confirms what we were saying last time, that UTF-8 and ASCII are identical on the ASCII characters." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## The with keyword\n", - "\n", - "So far, I've been drilling the importance of safely opening and closing files. But now, we're going to basically forget all that and show a better, safer way of opening files. You may have already seen it if you've been watching the videos closely. Check out this code:" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "This is a text file,\n", - "UTF-8 encoding.\n", - "It has two line breaks.\n" - ] - } - ], - "source": [ - "with open('haiku.txt', 'r', encoding='UTF-8') as haiku:\n", - " haiku_string = haiku.read()\n", - " \n", - "print(haiku_string)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And now, I don't need to close it. In fact, it's already closed. The with block opens the file only for the duration of the code in the block, and closes it when the with block has finished executing. The best part is that this happens regardless of why the with block finished executing, even if it's caused by a crash or if most of the block is skipped by if-statements.\n", - "\n", - "You should use with when you open files, extract the information you need from inside the with block, and then just move on, allowing with to close the file for you to free up the resources. The syntax is simple -- the open() function works just as before. The as keyword just assigns it to a variable.\n", - "\n", - "This method can be used for reading and writing files, and is the safest and most \"Pythonic\" way to work with files." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.1" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/PurePy 7. Importing Data/.ipynb_checkpoints/7.2 Reading and storing data; CSV, JSON, and more-checkpoint.ipynb b/PurePy 7. Importing Data/.ipynb_checkpoints/7.2 Reading and storing data; CSV, JSON, and more-checkpoint.ipynb deleted file mode 100644 index b154141..0000000 --- a/PurePy 7. Importing Data/.ipynb_checkpoints/7.2 Reading and storing data; CSV, JSON, and more-checkpoint.ipynb +++ /dev/null @@ -1,738 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There is a natural dichotomy between data files that are easy for a computer to read, and data files that are easy for a human to read. In this article, we'll look at three common kinds of data files you are likely to encounter, are fairly human-readable, as well as being very easily manipulated in Python.\n", - "\n", - "## CSV files\n", - "\n", - "CSV is a very simple file format. The initials stand for \"comma-separated values\", and is used to encode a table of data. All spreadsheets and most databases can be exported into CSV format, and spreadsheet software such as Excel can import CSV files, so this is a nice format to be familiar with. Line-breaks (that is, \\n or \\r characters) separate the rows, and commas separate the values in each row. Well, it's a bit more lenient than that; you can choose any character to separate the values, but comma is the one that stuck around in the name for some reason. So, this is a perfectly reasonable .csv file:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "item,price\n", - "bread,1.50\n", - "rice,3.00\n", - "bananas,0.30\n", - "applesauce,2.00" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "but so is" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "item|price\n", - "bread|1.50\n", - "rice|3.00\n", - "bananas|0.30\n", - "applesauce|2.00" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As we should have come to expect in Python, there is a standard library module for handling .csv files, called (wait for it) csv. The two main functions offered by this module are reader() and writer(), respectively used for reading and writing csv files. Let's look at reading, first." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['movie name', ' gross', 'IMDB rating', 'IMDB votes']\n", - "['Captain America: Civil War', ' 1153304495', '7.9', '418614']\n", - "['Rogue One', ' 1056057273', '7.9', '334132']\n", - "['Finding Dory', ' 1028570889', '7.4', '161213']\n", - "['Zootopia', ' 1023784195', '8.1', '302479']\n", - "['The Jungle Book', ' 966550600', '7.5', '200798']\n", - "['The Secret Life Of Pets', ' 875457937', '6.6', '124027']\n", - "['Batman v Superman', ' 873260194', '6.7', '479880']\n", - "['Deadpool', ' 783112979', '8.0', '637685']\n", - "['Suicide Squad', ' 745600054', '6.2', '404862']\n", - "['Sing', ' 632443719', '7.2', '66129']\n" - ] - } - ], - "source": [ - "import csv\n", - "with open('topmovies.csv', encoding='UTF-8') as f: # file contains highest grossing films of 2016\n", - " moviescsv = csv.reader(f, delimiter=',')\n", - "\n", - " for line in moviescsv:\n", - " print(line)\n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As we can see, each line is turned into a list of strings (by default). In this use of reader, we specified a delimiter character -- the character that separates each entry. We chose a comma, although this is redundant since it is the default anyway.\n", - "\n", - "We can see a problem with this import. Most entries have a space following the comma, which we don't want. This is easily fixed:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['movie name', 'gross', 'IMDB rating', 'IMDB votes']\n", - "['Captain America: Civil War', '1153304495', '7.9', '418614']\n", - "['Rogue One', '1056057273', '7.9', '334132']\n", - "['Finding Dory', '1028570889', '7.4', '161213']\n", - "['Zootopia', '1023784195', '8.1', '302479']\n", - "['The Jungle Book', '966550600', '7.5', '200798']\n", - "['The Secret Life Of Pets', '875457937', '6.6', '124027']\n", - "['Batman v Superman', '873260194', '6.7', '479880']\n", - "['Deadpool', '783112979', '8.0', '637685']\n", - "['Suicide Squad', '745600054', '6.2', '404862']\n", - "['Sing', '632443719', '7.2', '66129']\n" - ] - } - ], - "source": [ - "with open('topmovies.csv', encoding='UTF-8') as f:\n", - " moviescsv = csv.reader(f, delimiter=',', skipinitialspace=True)\n", - "\n", - " for line in moviescsv:\n", - " print(line)\n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The csv.reader object provides a large number of options and fixes to get the import just right. Another consideration with csvs is \"what if the entry contains the delimiter?\" For example, what if one of the movie titles in the file I imported contained a comma? For this, we use quotes: punctuation inside quotation marks is ignored. Hence, the csv reader also allows us to specify which character is used for quoting.\n", - "\n", - "The csv.reader object has not created a copy of the csv file in Python's memory; it is still reading from the file. Therefore, the file must still be open when we access the lines via the reader. If we want to close the file, we should move the entries into another structure such as a list or dictionary:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[['movie name', 'gross', 'IMDB rating', 'IMDB votes'], ['Captain America: Civil War', '1153304495', '7.9', '418614'], ['Rogue One', '1056057273', '7.9', '334132'], ['Finding Dory', '1028570889', '7.4', '161213'], ['Zootopia', '1023784195', '8.1', '302479'], ['The Jungle Book', '966550600', '7.5', '200798'], ['The Secret Life Of Pets', '875457937', '6.6', '124027'], ['Batman v Superman', '873260194', '6.7', '479880'], ['Deadpool', '783112979', '8.0', '637685'], ['Suicide Squad', '745600054', '6.2', '404862'], ['Sing', '632443719', '7.2', '66129']]\n" - ] - } - ], - "source": [ - "with open('topmovies.csv', encoding='UTF-8') as f:\n", - " moviescsv = csv.reader(f, delimiter=',', skipinitialspace=True)\n", - "\n", - " movielist = [line for line in moviescsv]\n", - "\n", - "print(movielist)\n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This is, of course, a rather crude demonstration (in fact it breaks our rule of avoiding lists of mixed types); we'd likely want to be more organized with how we structure the data we obtain from a csv, but that will depend on your individual needs.\n", - "\n", - "Writing to a csv is basically just as easy, and follows practically the same format. Let's put the movielist into a new csv, with different delimiters, and quotation marks around non-numeric data (this will make it easier to import in the future, since with this style, the reader can distinguish between numbers and strings when it reads the file. Firstly, we should actually convert the numeric data into numbers:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[['movie name', 'gross', 'IMDB rating', 'IMDB votes'], ['Captain America: Civil War', 1153304495.0, 7.9, 418614.0], ['Rogue One', 1056057273.0, 7.9, 334132.0], ['Finding Dory', 1028570889.0, 7.4, 161213.0], ['Zootopia', 1023784195.0, 8.1, 302479.0], ['The Jungle Book', 966550600.0, 7.5, 200798.0], ['The Secret Life Of Pets', 875457937.0, 6.6, 124027.0], ['Batman v Superman', 873260194.0, 6.7, 479880.0], ['Deadpool', 783112979.0, 8.0, 637685.0], ['Suicide Squad', 745600054.0, 6.2, 404862.0], ['Sing', 632443719.0, 7.2, 66129.0]]\n" - ] - } - ], - "source": [ - "for row in movielist:\n", - " for i, entry in enumerate(row):\n", - " try:\n", - " row[i] = float(entry)\n", - " except ValueError:\n", - " pass\n", - "\n", - "print(movielist)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Exactly how this code works will be explained in a future article, but try and guess what it does anyway! (Clue: float(\"movie name\") will usually produce an error. What do try and except do?) " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that our table is in a nicer format, let's write it to a csv." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "with open(\"movies-new.csv\", \"w\", encoding='UTF-8') as f:\n", - " # creates a \"writer\" that is ready to write whatever we give to it\n", - " moviecsv = csv.writer(f, delimiter='|', quotechar=\"`\", quoting=csv.QUOTE_NONNUMERIC)\n", - " \n", - " # give the list to the writer\n", - " moviecsv.writerows(movielist)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The resulting file on my computer looks like this:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "`movie name`|`gross`|`IMDB rating`|`IMDB votes`\n", - "`Captain America: Civil War`|1153304495.0|7.9|418614.0\n", - "`Rogue One`|1056057273.0|7.9|334132.0\n", - "`Finding Dory`|1028570889.0|7.4|161213.0\n", - "`Zootopia`|1023784195.0|8.1|302479.0\n", - "`The Jungle Book`|966550600.0|7.5|200798.0\n", - "`The Secret Life Of Pets`|875457937.0|6.6|124027.0\n", - "`Batman v Superman`|873260194.0|6.7|479880.0\n", - "`Deadpool`|783112979.0|8.0|637685.0\n", - "`Suicide Squad`|745600054.0|6.2|404862.0\n", - "`Sing`|632443719.0|7.2|66129.0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Each argument here should be fairly self-explanatory. Rows can be written one at a time with writer.writerow(row), instead of providing a full list all at once." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## JSON\n", - "\n", - "JSON stands for \"JavaScript Object Notation\". JavaScript is a programming languaged used to make interactive and dynamic webpages. This means there needs to be a way for a JavaScript script in a webpage to send and receive bundles of data without reloading the whole page. The JSON file format is one such solution. However, JSON files can be used to store many kinds of data, and are commonly encountered when grabbing information from the web. In fact, Jupyter notebook files such as this very article are really just JSON files with a different suffix; try opening one in your text editor to see for yourself!\n", - "\n", - "Thankfully for us, JSON files are easy for any Python programmer to understand. Here is an example of a JSON file containing an Amazon review for a piece of audio equipment (and yes, Amazon reviews really are sent over to your computer as JSON - in fact most of the things you see on any given Amazon page are):" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "{\"reviewerID\": \"A2C00NNG1ZQQG2\",\n", - "\"asin\": \"1384719342\",\n", - "\"reviewerName\": \"RustyBill \\\"Sunday Rocker\\\"\",\n", - "\"helpful\": [0, 0],\n", - "\"reviewText\": \"Nice windscreen protects my MXL mic and prevents pops. Only thing is that the gooseneck is only marginally able to hold the screen in position and requires careful positioning of the clamp to avoid sagging.\",\n", - "\"overall\": 5.0,\n", - "\"summary\": \"GOOD WINDSCREEN FOR THE MONEY\",\n", - "\"unixReviewTime\": 1392336000,\n", - "\"reviewTime\": \"02 14, 2014\"}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Look familiar? It's basically just a dictionary. This is a good reason for Python programmers to know about JSON files, as it means we can save the data in our Python programs on an external file, so long as the values are of a suitable format (strings, numbers, etc)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Of course, it's not precisely a dictionary. There are some translations that need to be made from the JSON format (and terminology). The dictionary-like structure of a JSON file is called a JSON object. Since objects can have objects as their values, this gives JSON objects a tree-like structure. Booleans in JSON files use all lower case (so Python's True is true in JSON). Lists and tuples are rolled into one object called an array, and all floats and ints are rolled into one object called a number. Let's see how we can import JSONs, using the json module, which does all the necessary translations for us (phew!)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The main functions of the module are dump and dumps (for creating JSON objects), and load and loads (for reading JSON objects). The s appearing in two of these functions simply stands for string. We'll see the difference in a second." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'reviewerID': 'A2IBPI20UZIR0U', 'asin': '1384719342', 'reviewerName': 'cassandra tu \"Yeah, well, that\\'s just like, u...', 'helpful': [0, 0], 'reviewText': \"Not much to write about here, but it does exactly what it's supposed to. filters out the pop sounds. now my recordings are much more crisp. it is one of the lowest prices pop filters on amazon so might as well buy it, they honestly work the same despite their pricing,\", 'overall': 5.0, 'summary': 'good', 'unixReviewTime': 1393545600, 'reviewTime': '02 28, 2014'}\n", - "{'reviewerID': 'A14VAT5EAX3D9S', 'asin': '1384719342', 'reviewerName': 'Jake', 'helpful': [13, 14], 'reviewText': \"The product does exactly as it should and is quite affordable.I did not realized it was double screened until it arrived, so it was even better than I had expected.As an added bonus, one of the screens carries a small hint of the smell of an old grape candy I used to buy, so for reminiscent's sake, I cannot stop putting the pop filter next to my nose and smelling it after recording. :DIf you needed a pop filter, this will work just as well as the expensive ones, and it may even come with a pleasing aroma like mine did!Buy this product! :]\", 'overall': 5.0, 'summary': 'Jake', 'unixReviewTime': 1363392000, 'reviewTime': '03 16, 2013'}\n", - "{'reviewerID': 'A195EZSQDW3E21', 'asin': '1384719342', 'reviewerName': 'Rick Bennette \"Rick Bennette\"', 'helpful': [1, 1], 'reviewText': 'The primary job of this device is to block the breath that would otherwise produce a popping sound, while allowing your voice to pass through with no noticeable reduction of volume or high frequencies. The double cloth filter blocks the pops and lets the voice through with no coloration. The metal clamp mount attaches to the mike stand secure enough to keep it attached. The goose neck needs a little coaxing to stay where you put it.', 'overall': 5.0, 'summary': 'It Does The Job Well', 'unixReviewTime': 1377648000, 'reviewTime': '08 28, 2013'}\n", - "{'reviewerID': 'A2C00NNG1ZQQG2', 'asin': '1384719342', 'reviewerName': 'RustyBill \"Sunday Rocker\"', 'helpful': [0, 0], 'reviewText': 'Nice windscreen protects my MXL mic and prevents pops. Only thing is that the gooseneck is only marginally able to hold the screen in position and requires careful positioning of the clamp to avoid sagging.', 'overall': 5.0, 'summary': 'GOOD WINDSCREEN FOR THE MONEY', 'unixReviewTime': 1392336000, 'reviewTime': '02 14, 2014'}\n", - "{'reviewerID': 'A94QU4C90B1AX', 'asin': '1384719342', 'reviewerName': 'SEAN MASLANKA', 'helpful': [0, 0], 'reviewText': \"This pop filter is great. It looks and performs like a studio filter. If you're recording vocals this will eliminate the pops that gets recorded when you sing.\", 'overall': 5.0, 'summary': 'No more pops when I record my vocals.', 'unixReviewTime': 1392940800, 'reviewTime': '02 21, 2014'}\n" - ] - } - ], - "source": [ - "import json\n", - "with open(\"Musical_Instruments_5.json\", \"r\", encoding='UTF-8') as f:\n", - " reviews = [json.loads(line) for line in f]\n", - "\n", - "for review in reviews[:5]:\n", - " print(review)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's break it down. As usual, we open the file using open to give us a file object. This file contains a different JSON object on each line. Because we can read through a file line-by-line, and those lines are read as text, we use loads because each line is a string.\n", - "\n", - "One we have loaded it, each JSON object is now precisely a dictionary:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "This person thought the product they purchased was: good\n" - ] - } - ], - "source": [ - "print(type(reviews[0]))\n", - "print(\"This person thought the product they purchased was: {}\".format(reviews[0][\"summary\"]))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This strategy is very good when we have a file containing lots of JSON objects. We read each object (line) as a string and then pass it to loads to convert it. If we have a file containing only a single JSON object, we can pass the whole file to load instead:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Spiritually and mentally inspiring! A book that allows you to question your morals and will help you discover who you really are!\n" - ] - } - ], - "source": [ - "with open(\"book_review.json\", encoding='UTF-8') as f:\n", - " bookreview = json.load(f)\n", - "\n", - "print(bookreview[\"reviewText\"])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Writing JSON objects to files is much the same scenario. This provides a convenient way to save the important information in a Python program, in a way that can be re-opened by the same program, another Python program, or even a program written in a different programming language.\n", - "\n", - "Let's encode a JSON object. Suppose I run a business and my program is storing the delivery details of my customers. I might store each customer as a dictionary like this:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "customer = {\n", - " 'name': 'Sam Cassidy',\n", - " 'address': '19 Notareal Avenue, Liverpool',\n", - " 'postcode': 'L00 9JR',\n", - " 'purchase-history': [('inflatable pet', 3, '05.09.2016'),\n", - " ('disposable widget', 60, '01.01.2017')],\n", - " 'Phone number': '0712345567889'\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So the information contained here is mostly strings, although some are organized into lists of tuples, and there's also a couple of integers here as well. Let's create a JSON object from this dictionary." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "customer_JSON = json.dumps(customer)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\"name\": \"Sam Cassidy\", \"address\": \"19 Notareal Avenue, Liverpool\", \"postcode\": \"L00 9JR\", \"purchase-history\": [[\"inflatable pet\", 3, \"05.09.2016\"], [\"disposable widget\", 60, \"01.01.2017\"]]}\n" - ] - } - ], - "source": [ - "print(customer_JSON)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As we can see, the reproduction is mostly faithful, but our tuples have been turned into JSON arrays. That's okay: if we wish to recover the original tuples when we load from this JSON file, we can just write a function to convert them back.\n", - "\n", - "JSON files ignore whitespace, so we can actually make a slightly nicer JSON file by setting the indent parameter:" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"name\": \"Sam Cassidy\",\n", - " \"address\": \"19 Notareal Avenue, Liverpool\",\n", - " \"postcode\": \"L00 9JR\",\n", - " \"purchase-history\": [\n", - " [\n", - " \"inflatable pet\",\n", - " 3,\n", - " \"05.09.2016\"\n", - " ],\n", - " [\n", - " \"disposable widget\",\n", - " 60,\n", - " \"01.01.2017\"\n", - " ]\n", - " ]\n", - "}\n" - ] - } - ], - "source": [ - "customer_JSON = json.dumps(customer, indent=2)\n", - "print(customer_JSON)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Which is easier to read, and closer to how we defined customer in the file. Since this is now just a string, we can write it to a .json file using the usual write methods:" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "with open('my_customers.json', 'a', encoding='UTF-8') as f:\n", - " f.write(customer_JSON)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And there, the data is saved and can be reopened using json.load() or json.loads().\n", - "\n", - "The difficulty with JSON files is that ultimately, they're only text files. For one, this means encoding is sometimes important, and all the previous things we've said about encoding should be considered. For two, this means that more complicated Python data structures (for example custom made classes, which we'll meet soon enough) might need to be cleverly converted into text, somehow or other. For instance, it might be more useful to inside my program to work with Python's smart \"date\" objects, rather than just strings containing the date:" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "from datetime import date\n", - "customer = {\n", - " 'name': 'Sam Cassidy',\n", - " 'address': '19 Notareal Avenue, Liverpool',\n", - " 'postcode': 'L00 9JR',\n", - " 'purchase-history': [('inflatable pet', 3, date(2016, 9, 5)),\n", - " ('disposable widget', 60, date(2017, 1, 1))],\n", - " 'Phone number': '0712345567889'\n", - "}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The date object is much smarter than a string. For example:" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2016-09-05\n", - "1\n", - "Monday 05 September\n" - ] - } - ], - "source": [ - "inflatable_pet_date = customer['purchase-history'][0][2]\n", - "print(inflatable_pet_date)\n", - "print(inflatable_pet_date.isoweekday()) # day of the week as a number-- this day was a Monday (1st day)!\n", - "print(inflatable_pet_date.strftime('%A %d %B')) # there's a little mini language to control\n", - " # this representatio" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's write this object to a JSON again:" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "Object of type 'date' is not JSON serializable", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mcustomer_JSON\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mjson\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdumps\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcustomer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mindent\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/__init__.py\u001b[0m in \u001b[0;36mdumps\u001b[0;34m(obj, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, default, sort_keys, **kw)\u001b[0m\n\u001b[1;32m 236\u001b[0m \u001b[0mcheck_circular\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcheck_circular\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mallow_nan\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mallow_nan\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mindent\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mindent\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 237\u001b[0m \u001b[0mseparators\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mseparators\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdefault\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdefault\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msort_keys\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0msort_keys\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 238\u001b[0;31m **kw).encode(obj)\n\u001b[0m\u001b[1;32m 239\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 240\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/encoder.py\u001b[0m in \u001b[0;36mencode\u001b[0;34m(self, o)\u001b[0m\n\u001b[1;32m 199\u001b[0m \u001b[0mchunks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0miterencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_one_shot\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 200\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mchunks\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mlist\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 201\u001b[0;31m \u001b[0mchunks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mchunks\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 202\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mchunks\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 203\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/encoder.py\u001b[0m in \u001b[0;36m_iterencode\u001b[0;34m(o, _current_indent_level)\u001b[0m\n\u001b[1;32m 428\u001b[0m \u001b[0;32myield\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0m_iterencode_list\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_current_indent_level\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 429\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdict\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 430\u001b[0;31m \u001b[0;32myield\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0m_iterencode_dict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_current_indent_level\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 431\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 432\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mmarkers\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/encoder.py\u001b[0m in \u001b[0;36m_iterencode_dict\u001b[0;34m(dct, _current_indent_level)\u001b[0m\n\u001b[1;32m 402\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 403\u001b[0m \u001b[0mchunks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_iterencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_current_indent_level\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 404\u001b[0;31m \u001b[0;32myield\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mchunks\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 405\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mnewline_indent\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 406\u001b[0m \u001b[0m_current_indent_level\u001b[0m \u001b[0;34m-=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/encoder.py\u001b[0m in \u001b[0;36m_iterencode_list\u001b[0;34m(lst, _current_indent_level)\u001b[0m\n\u001b[1;32m 323\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 324\u001b[0m \u001b[0mchunks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_iterencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_current_indent_level\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 325\u001b[0;31m \u001b[0;32myield\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mchunks\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 326\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mnewline_indent\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 327\u001b[0m \u001b[0m_current_indent_level\u001b[0m \u001b[0;34m-=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/encoder.py\u001b[0m in \u001b[0;36m_iterencode_list\u001b[0;34m(lst, _current_indent_level)\u001b[0m\n\u001b[1;32m 323\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 324\u001b[0m \u001b[0mchunks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_iterencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_current_indent_level\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 325\u001b[0;31m \u001b[0;32myield\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mchunks\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 326\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mnewline_indent\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 327\u001b[0m \u001b[0m_current_indent_level\u001b[0m \u001b[0;34m-=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/encoder.py\u001b[0m in \u001b[0;36m_iterencode\u001b[0;34m(o, _current_indent_level)\u001b[0m\n\u001b[1;32m 435\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Circular reference detected\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 436\u001b[0m \u001b[0mmarkers\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mmarkerid\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mo\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 437\u001b[0;31m \u001b[0mo\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_default\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mo\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 438\u001b[0m \u001b[0;32myield\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0m_iterencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_current_indent_level\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 439\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mmarkers\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/encoder.py\u001b[0m in \u001b[0;36mdefault\u001b[0;34m(self, o)\u001b[0m\n\u001b[1;32m 178\u001b[0m \"\"\"\n\u001b[1;32m 179\u001b[0m raise TypeError(\"Object of type '%s' is not JSON serializable\" %\n\u001b[0;32m--> 180\u001b[0;31m o.__class__.__name__)\n\u001b[0m\u001b[1;32m 181\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 182\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mo\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mTypeError\u001b[0m: Object of type 'date' is not JSON serializable" - ] - } - ], - "source": [ - "customer_JSON = json.dumps(customer, indent=2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Umm... ouch. A simple solution is to write functions that can convert to and from strings and date objects, and just apply them before and after encoding or decoding. The date module of course already provides a way to convert the date to a string -- you can just use str() on the object." - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def customer_to_jsonable(customer):\n", - " from copy import copy\n", - " # so we don't damage the original dictionary\n", - " customer = copy(customer)\n", - " for i, entry in enumerate(customer['purchase-history']):\n", - " customer['purchase-history'][i] = (entry[0], entry[1], str(entry[2]))\n", - " return customer\n", - "\n", - "def json_to_customer(jsonCust):\n", - " for i, entry in enumerate(jsonCust['purchase-history']):\n", - " date_list = entry[2].split('-')\n", - " date_list = [int(x) for x in date_list]\n", - " jsonCust['purchase-history'][i] = (entry[0], entry[1], date(date_list[0], date_list[1], date_list[2]))\n", - " return jsonCust\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# now call the function before converting to JSON\n", - "customer_JSON = json.dumps(customer_to_jsonable(customer), indent=2)" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\n", - " \"name\": \"Sam Cassidy\",\n", - " \"address\": \"19 Notareal Avenue, Liverpool\",\n", - " \"postcode\": \"L00 9JR\",\n", - " \"purchase-history\": [\n", - " [\n", - " \"inflatable pet\",\n", - " 3,\n", - " \"2016-09-05\"\n", - " ],\n", - " [\n", - " \"disposable widget\",\n", - " 60,\n", - " \"2017-01-01\"\n", - " ]\n", - " ],\n", - " \"Phone number\": \"0712345567889\"\n", - "}\n" - ] - } - ], - "source": [ - "print(customer_JSON)" - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'name': 'Sam Cassidy', 'address': '19 Notareal Avenue, Liverpool', 'postcode': 'L00 9JR', 'purchase-history': [('inflatable pet', 3, datetime.date(2016, 9, 5)), ('disposable widget', 60, datetime.date(2017, 1, 1))], 'Phone number': '0712345567889'} \n", - "\n", - "Customer Sam Cassidy purchased inflatable pet on:\n", - "2016-09-05\n" - ] - } - ], - "source": [ - "original_customer = json_to_customer(json.loads(customer_JSON))\n", - "print(original_customer, '\\n')\n", - "print(\"Customer {} purchased {} on:\".format(original_customer['name'],\n", - " original_customer['purchase-history'][0][0]))\n", - "print(original_customer['purchase-history'][0][2])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So, with a little bit of thinking and tinkering, we've recovered all of the original information, even though JSON only allows us to store text.\n", - "\n", - "## XML\n", - "\n", - "There's another very common way to store and manipulate data on the web. It's called XML, and is in many ways like JSON, but more flexible, and more complicated. Python has an xml module for working with these formats, which again converts hierarchies of attributes into dictionary. There's a great article about how the format works and how to use xml here: http://www.diveintopython3.net/xml.html." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.1" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/PurePy 7. Importing Data/.ipynb_checkpoints/Reading and storing data; CSV, JSON, and XML-checkpoint.ipynb b/PurePy 7. Importing Data/.ipynb_checkpoints/Reading and storing data; CSV, JSON, and XML-checkpoint.ipynb deleted file mode 100644 index 8cf85c3..0000000 --- a/PurePy 7. Importing Data/.ipynb_checkpoints/Reading and storing data; CSV, JSON, and XML-checkpoint.ipynb +++ /dev/null @@ -1,417 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There is a natural dichotomy between data files that are easy for a computer to read, and data files that are easy for a human to read. In this article, we'll look at three common kinds of data files you are likely to encounter, are fairly human-readable, as well as being very easily manipulated in Python.\n", - "\n", - "## CSV files\n", - "\n", - "CSV is a very simple file format. The initials stand for \"comma-separated values\", and is used to encode a table of data. All spreadsheets and most databases can be exported into CSV format, and spreadsheet software such as Excel can import CSV files, so this is a nice format to be familiar with. Line-breaks (that is, \\n or \\r characters) separate the rows, and commas separate the values in each row. Well, it's a bit more lenient than that; you can choose any character to separate the values, but comma is the one that stuck around in the name for some reason. So, this is a perfectly reasonable .csv file:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "item,price\n", - "bread,1.50\n", - "rice,3.00\n", - "bananas,0.30\n", - "applesauce,2.00" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "but so is" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "item|price\n", - "bread|1.50\n", - "rice|3.00\n", - "bananas|0.30\n", - "applesauce|2.00" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As we should have come to expect in Python, there is a standard library module for handling .csv files, called (wait for it) csv. The two main functions offered by this module are reader() and writer(), respectively used for reading and writing csv files. Let's look at reading, first." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Pretty printing has been turned ON\n", - "['movie name', ' gross', 'IMDB rating', 'IMDB votes']\n", - "['Captain America: Civil War', ' 1153304495', '7.9', '418614']\n", - "['Rogue One', ' 1056057273', '7.9', '334132']\n", - "['Finding Dory', ' 1028570889', '7.4', '161213']\n", - "['Zootopia', ' 1023784195', '8.1', '302479']\n", - "['The Jungle Book', ' 966550600', '7.5', '200798']\n", - "['The Secret Life Of Pets', ' 875457937', '6.6', '124027']\n", - "['Batman v Superman', ' 873260194', '6.7', '479880']\n", - "['Deadpool', ' 783112979', '8.0', '637685']\n", - "['Suicide Squad', ' 745600054', '6.2', '404862']\n", - "['Sing', ' 632443719', '7.2', '66129']\n" - ] - } - ], - "source": [ - "import csv\n", - "with open('topmovies.csv', newline='') as f: # file contains highest grossing films of 2016\n", - " moviescsv = csv.reader(f, delimiter=',')\n", - "\n", - " for line in moviescsv:\n", - " print(line)\n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As we can see, each line is turned into a list of strings (by default). In this use of reader, we specified a delimiter character -- the character that separates each entry. We chose a comma, although this is redundant since it is the default anyway.\n", - "\n", - "We can see a problem with this import. Most entries have a space following the comma, which we don't want. This is easily fixed:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['movie name', 'gross', 'IMDB rating', 'IMDB votes']\n", - "['Captain America: Civil War', '1153304495', '7.9', '418614']\n", - "['Rogue One', '1056057273', '7.9', '334132']\n", - "['Finding Dory', '1028570889', '7.4', '161213']\n", - "['Zootopia', '1023784195', '8.1', '302479']\n", - "['The Jungle Book', '966550600', '7.5', '200798']\n", - "['The Secret Life Of Pets', '875457937', '6.6', '124027']\n", - "['Batman v Superman', '873260194', '6.7', '479880']\n", - "['Deadpool', '783112979', '8.0', '637685']\n", - "['Suicide Squad', '745600054', '6.2', '404862']\n", - "['Sing', '632443719', '7.2', '66129']\n" - ] - } - ], - "source": [ - "with open('topmovies.csv', newline='') as f:\n", - " moviescsv = csv.reader(f, delimiter=',', skipinitialspace=True)\n", - "\n", - " for line in moviescsv:\n", - " print(line)\n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The csv.reader object provides a large number of options and fixes to get the import just right. Another consideration with csvs is \"what if the entry contains the delimiter?\" For example, what if one of the movie titles in the file I imported contained a comma? For this, we use quotes: punctuation inside quotation marks is ignored. Hence, the csv reader also allows us to specify which character is used for quoting.\n", - "\n", - "The csv.reader object has not created a copy of the csv file in Python's memory; it is still reading from the file. Therefore, the file must still be open when we access the lines via the reader. If we want to close the file, we should move the entries into another structure such as a list or dictionary:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[['movie name', 'gross', 'IMDB rating', 'IMDB votes'], ['Captain America: Civil War', '1153304495', '7.9', '418614'], ['Rogue One', '1056057273', '7.9', '334132'], ['Finding Dory', '1028570889', '7.4', '161213'], ['Zootopia', '1023784195', '8.1', '302479'], ['The Jungle Book', '966550600', '7.5', '200798'], ['The Secret Life Of Pets', '875457937', '6.6', '124027'], ['Batman v Superman', '873260194', '6.7', '479880'], ['Deadpool', '783112979', '8.0', '637685'], ['Suicide Squad', '745600054', '6.2', '404862'], ['Sing', '632443719', '7.2', '66129']]\n" - ] - } - ], - "source": [ - "with open('topmovies.csv', newline='') as f:\n", - " moviescsv = csv.reader(f, delimiter=',', skipinitialspace=True)\n", - "\n", - " movielist = [line for line in moviescsv]\n", - "\n", - "print(movielist)\n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This is, of course, a rather crude demonstration (in fact it breaks our rule of avoiding lists of mixed types); we'd likely want to be more organized with how we structure the data we obtain from a csv, but that will depend on your individual needs.\n", - "\n", - "Writing to a csv is basically just as easy, and follows practically the same format. Let's put the movielist into a new csv, with different delimiters, and quotation marks around non-numeric data (this will make it easier to import in the future, since with this style, the reader can distinguish between numbers and strings when it reads the file. Firstly, we should actually convert the numeric data into numbers:" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[['movie name', 'gross', 'IMDB rating', 'IMDB votes'], ['Captain America: Civil War', 1153304495.0, 7.9, 418614.0], ['Rogue One', 1056057273.0, 7.9, 334132.0], ['Finding Dory', 1028570889.0, 7.4, 161213.0], ['Zootopia', 1023784195.0, 8.1, 302479.0], ['The Jungle Book', 966550600.0, 7.5, 200798.0], ['The Secret Life Of Pets', 875457937.0, 6.6, 124027.0], ['Batman v Superman', 873260194.0, 6.7, 479880.0], ['Deadpool', 783112979.0, 8.0, 637685.0], ['Suicide Squad', 745600054.0, 6.2, 404862.0], ['Sing', 632443719.0, 7.2, 66129.0]]\n" - ] - } - ], - "source": [ - "for row in movielist:\n", - " for i, entry in enumerate(row):\n", - " try:\n", - " row[i] = float(entry)\n", - " except ValueError:\n", - " pass\n", - "\n", - "print(movielist)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Exactly how this code works will be explained in a future article, but try and guess what it does anyway! (Clue: float(\"movie name\") will usually produce an error. What do try and except do?) " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that our table is in a nicer format, let's write it to a csv." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "with open(\"movies-new.csv\", \"w\", newline='') as f:\n", - " # creates a \"writer\" that is ready to write whatever we give to it\n", - " moviecsv = csv.writer(f, delimiter='|', quotechar=\"`\", quoting=csv.QUOTE_NONNUMERIC)\n", - " \n", - " # give the list to the writer\n", - " moviecsv.writerows(movielist)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The resulting file on my computer looks like this:" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "`movie name`|`gross`|`IMDB rating`|`IMDB votes`\n", - "`Captain America: Civil War`|1153304495.0|7.9|418614.0\n", - "`Rogue One`|1056057273.0|7.9|334132.0\n", - "`Finding Dory`|1028570889.0|7.4|161213.0\n", - "`Zootopia`|1023784195.0|8.1|302479.0\n", - "`The Jungle Book`|966550600.0|7.5|200798.0\n", - "`The Secret Life Of Pets`|875457937.0|6.6|124027.0\n", - "`Batman v Superman`|873260194.0|6.7|479880.0\n", - "`Deadpool`|783112979.0|8.0|637685.0\n", - "`Suicide Squad`|745600054.0|6.2|404862.0\n", - "`Sing`|632443719.0|7.2|66129.0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Each argument here should be fairly self-explanatory. Rows can be written one at a time with writer.writerow(row), instead of providing a full list all at once." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## JSON\n", - "\n", - "JSON stands for \"JavaScript Object Notation\". JavaScript is a programming languaged used to make interactive and dynamic webpages. This means there needs to be a way for a JavaScript script in a webpage to send and receive bundles of data without reloading the whole page. The JSON file format is one such solution. However, JSON files can be used to store many kinds of data, and are commonly encountered when grabbing information from the web. In fact, Jupyter notebook files such as this very article are really just JSON files with a different suffix; try opening one in your text editor to see for yourself!\n", - "\n", - "Thankfully for us, JSON files are easy for any Python programmer to understand. Here is an example of a JSON file containing an Amazon review for a piece of audio equipment (and yes, Amazon reviews really are sent over to your computer as JSON - in fact most of the things you see on any given Amazon page are):" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "{\"reviewerID\": \"A2C00NNG1ZQQG2\",\n", - "\"asin\": \"1384719342\",\n", - "\"reviewerName\": \"RustyBill \\\"Sunday Rocker\\\"\",\n", - "\"helpful\": [0, 0],\n", - "\"reviewText\": \"Nice windscreen protects my MXL mic and prevents pops. Only thing is that the gooseneck is only marginally able to hold the screen in position and requires careful positioning of the clamp to avoid sagging.\",\n", - "\"overall\": 5.0,\n", - "\"summary\": \"GOOD WINDSCREEN FOR THE MONEY\",\n", - "\"unixReviewTime\": 1392336000,\n", - "\"reviewTime\": \"02 14, 2014\"}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Look familiar? It's basically just a dictionary. This is a good reason for Python programmers to know about JSON files, as it means we can save the data in our dictionaries on an external file, so long as the values are of a suitable format (strings, numbers, etc)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Of course, it's not precisely a dictionary. There are some translations that need to be made from the JSON format (and terminology). The dictionary-like structure of a JSON file is called a JSON object. Since objects can have objects as their values, this gives JSON objects a tree-like structure. Booleans in JSON files use all lower case (so Python's True is true in JSON). Lists and tuples are rolled into one object called an array, and all floats and ints are rolled into one object called a number. Let's see how we can import JSONs, using the json module, which does all the necessary translations for us (phew!)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The main functions of the module are dump and dumps (for creating JSON objects), and load and loads (for reading JSON objects). The s appearing in two of these functions simply stands for string. We'll see the difference in a second." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'reviewTime': '02 28, 2014', 'reviewerID': 'A2IBPI20UZIR0U', 'reviewerName': 'cassandra tu \"Yeah, well, that\\'s just like, u...', 'overall': 5.0, 'summary': 'good', 'asin': '1384719342', 'helpful': [0, 0], 'reviewText': \"Not much to write about here, but it does exactly what it's supposed to. filters out the pop sounds. now my recordings are much more crisp. it is one of the lowest prices pop filters on amazon so might as well buy it, they honestly work the same despite their pricing,\", 'unixReviewTime': 1393545600}\n", - "{'reviewTime': '03 16, 2013', 'reviewerID': 'A14VAT5EAX3D9S', 'reviewerName': 'Jake', 'overall': 5.0, 'summary': 'Jake', 'asin': '1384719342', 'helpful': [13, 14], 'reviewText': \"The product does exactly as it should and is quite affordable.I did not realized it was double screened until it arrived, so it was even better than I had expected.As an added bonus, one of the screens carries a small hint of the smell of an old grape candy I used to buy, so for reminiscent's sake, I cannot stop putting the pop filter next to my nose and smelling it after recording. :DIf you needed a pop filter, this will work just as well as the expensive ones, and it may even come with a pleasing aroma like mine did!Buy this product! :]\", 'unixReviewTime': 1363392000}\n", - "{'reviewTime': '08 28, 2013', 'reviewerID': 'A195EZSQDW3E21', 'reviewerName': 'Rick Bennette \"Rick Bennette\"', 'overall': 5.0, 'summary': 'It Does The Job Well', 'asin': '1384719342', 'helpful': [1, 1], 'reviewText': 'The primary job of this device is to block the breath that would otherwise produce a popping sound, while allowing your voice to pass through with no noticeable reduction of volume or high frequencies. The double cloth filter blocks the pops and lets the voice through with no coloration. The metal clamp mount attaches to the mike stand secure enough to keep it attached. The goose neck needs a little coaxing to stay where you put it.', 'unixReviewTime': 1377648000}\n", - "{'reviewTime': '02 14, 2014', 'reviewerID': 'A2C00NNG1ZQQG2', 'reviewerName': 'RustyBill \"Sunday Rocker\"', 'overall': 5.0, 'summary': 'GOOD WINDSCREEN FOR THE MONEY', 'asin': '1384719342', 'helpful': [0, 0], 'reviewText': 'Nice windscreen protects my MXL mic and prevents pops. Only thing is that the gooseneck is only marginally able to hold the screen in position and requires careful positioning of the clamp to avoid sagging.', 'unixReviewTime': 1392336000}\n", - "{'reviewTime': '02 21, 2014', 'reviewerID': 'A94QU4C90B1AX', 'reviewerName': 'SEAN MASLANKA', 'overall': 5.0, 'summary': 'No more pops when I record my vocals.', 'asin': '1384719342', 'helpful': [0, 0], 'reviewText': \"This pop filter is great. It looks and performs like a studio filter. If you're recording vocals this will eliminate the pops that gets recorded when you sing.\", 'unixReviewTime': 1392940800}\n" - ] - } - ], - "source": [ - "import json\n", - "with open(\"Musical_Instruments_5.json\", \"r\") as f:\n", - " reviews = [json.loads(line) for line in f]\n", - "\n", - "for review in reviews[:5]:\n", - " print(review)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's break it down. As usual, we open the file using open to give us a file object. This file contains a different JSON object on each line. Because we can read through a file line-by-line, and those lines are read as text, we use loads because each line is a string.\n", - "\n", - "One we have loaded it, each JSON object is now precisely a dictionary:" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "This person thought the product they purchased was: good\n" - ] - } - ], - "source": [ - "print(type(reviews[0]))\n", - "print(\"This person thought the product they purchased was: {}\".format(reviews[0][\"summary\"]))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This strategy is very good when we have a file containing lots of JSON objects. We read each object (line) as a string and then pass it to loads to convert it. If we have a file containing only a single JSON object, we can pass the whole file to load instead:" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Spiritually and mentally inspiring! A book that allows you to question your morals and will help you discover who you really are!\n" - ] - } - ], - "source": [ - "with open(\"book_review.json\") as f:\n", - " bookreview = json.load(f)\n", - "\n", - "print(bookreview[\"reviewText\"])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Writing JSON objects to files is much the same scenario." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.2" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/PurePy 8. Advanced Flow Control/.ipynb_checkpoints/8.0 Advanced Flow Control-checkpoint.ipynb b/PurePy 8. Advanced Flow Control/.ipynb_checkpoints/8.0 Advanced Flow Control-checkpoint.ipynb deleted file mode 100644 index 9b6c130..0000000 --- a/PurePy 8. Advanced Flow Control/.ipynb_checkpoints/8.0 Advanced Flow Control-checkpoint.ipynb +++ /dev/null @@ -1,726 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# More Flow Control\n", - "\n", - "So far, we have met if, elif and else, as well as for-loops and while-loops. Now we take a look at some more tools we have to control the behaviour of loops. Briefly before that though." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## The pass statement" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The statement pass is simply the \"do nothing\" statement. Including this somewhere in your code does precisely nothing. However, it is formally a valid Python statement. Therefore it can be used as a placeholder in a location where Python formally requires some code, but you either don't want to do anything, or simply haven't got round to it. For example, when you start designing a sequence of ifs and elifs, you may want to write out each possible choice ahead of writing out what to do in each case. Hence, we might write the Fizzbuzz challenge first like this:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "for x in range(100):\n", - " if x % 3 == 0 and x % 5 == 0:\n", - " pass\n", - " elif x % 3 == 0:\n", - " pass\n", - " elif x % 5 == 0:\n", - " pass\n", - " else:\n", - " pass" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This way, we can see some of the structure of the program, even we've not filled in the details yet. This is particularly useful when you are breaking your problem down into different functions; you can easily see what is yet to be done, especially when combined with doc strings." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "## example here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## More logical checking tools\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Using other types as stand-ins for Booleans\n", - "\n", - "A neat thing about Python is that if we use a non-Boolean type in a logical expression, Python will have a go at interpreting it as a Boolean anyway.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n" - ] - } - ], - "source": [ - "print(1 and 0)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1\n" - ] - } - ], - "source": [ - "print(1 and 1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this case, Python knows to use 0 as False, and 1 as True. This works for all kinds of things, but the rule of thumb is this. If you give Python numbers in a boolean expression, 0 is considered False, anything non-zero is considered True (this applies to ints, floats, and complex numbers). If you given Python a sequence or container, such as a list or string (which is a sequence of letters), then an empty sequence is considered False and a non-empty sequence is considered True:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Cat\n" - ] - } - ], - "source": [ - "print(\"\" or \"Cat\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To convert something into a boolean in the more classical sense, use the bool() function: " - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(bool(\"\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(bool(\"Cat\"))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### In\n", - "\n", - "With many sequence or container-like objects, we can check for membership using in. For example:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print('cat' in \"concatenate\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(\"dog\" in [\"cat\", \"dog\", \"hamster\"])" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "# this is a set, a data structure we have not discussed.\n", - "# sets contain unordered data with no duplicates\n", - "# (identical entries are counted as a single entry)\n", - "# They are occasionally useful.\n", - "print(3 in {1, 2, 3})" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Identity: \"is\"\n", - "\n", - "We can check for two objects being actually the same object in Python's memory using is. This is, confusingly, different to using ==, which checks for some equality of value. This leads to some profoundly weird cases, especially with numbers and strings. Therefore the advice is to only use this in this in the situations I outline here. Let's see examples." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print([] is [])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Why did this evaluate False? Because writing an empty list [] always creates a brand new empty list. These are two different lists as far as Python is concerned. Hence is will come out as False. However:" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print([] == [])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This comes out as True. While these are different lists, they have the same contents, and Python can see this. So, we use is when we want Python to check not just that two things look similar, but are one and the same object.\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n", - "False\n" - ] - } - ], - "source": [ - "a = [\"spam\"]\n", - "b = a\n", - "c = [\"spam\"]\n", - "print(a is b)\n", - "print(c is a)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There is one more use case I have found useful. This is for checking the None type object. None is a special object, representing nothing, nada. A function that gives no return value gives None:" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "None\n" - ] - } - ], - "source": [ - "def gives_nothing():\n", - " pass\n", - "print(gives_nothing())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In many boolean situations, None is interpreted as False." - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Was interpreted as False\n" - ] - } - ], - "source": [ - "probably_false = None\n", - "if not probably_false:\n", - " print(\"Was interpreted as False\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "However, None and False are certainly not the same. If I have a function that sometimes returns a value and sometimes does not, and I want to check if the function returned None, I can use is:" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "gives_nothing() gave nothing\n" - ] - } - ], - "source": [ - "if gives_nothing() is None:\n", - " print(\"gives_nothing() gave nothing\")" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "if gives_nothing() is not None:\n", - " print(\"gives_nothing() gave something\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Looping over indices\n", - "\n", - "It is somewhat common, though to be avoided if feasible, to wish to loop over the indices of a list or other sequence, rather than the items of a list.\n", - "\n", - "There is a commonly used, naive way to do this. It is wrong, in the sense that it is ugly. Suppose I wish to print a list with numbering:" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1. Fruit\n", - "2. Coffee\n", - "3. Tofu\n", - "4. Rice\n", - "5. Soy sauce\n" - ] - } - ], - "source": [ - "shopping = [\"Fruit\", \"Coffee\", \"Tofu\", \"Rice\", \"Soy sauce\"]\n", - "## Ugly version:\n", - "for i in range(len(shopping)):\n", - " list_item = \"{}. {}\".format(i+1, shopping[i]) \n", - " print(list_item)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This is very common to see from both new and experienced programmers; in many programming languages, this kind of construction is the only way to perform this task. There is a much preferred method in Python, however:" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1. Fruit\n", - "2. Coffee\n", - "3. Tofu\n", - "4. Rice\n", - "5. Soy sauce\n" - ] - } - ], - "source": [ - "# Pythonic version\n", - "for i, grocery in enumerate(shopping):\n", - " list_item = \"{}. {}\".format(i+1, grocery)\n", - " print(list_item)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So, enumerate gives a sequence of tuples, the first being the index, the second being the element. Now we can use both. Fab!" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[(0, 'Fruit'), (1, 'Coffee'), (2, 'Tofu'), (3, 'Rice'), (4, 'Soy sauce')]\n" - ] - } - ], - "source": [ - "print(list(enumerate(shopping)))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break and continue\n", - "\n", - "We have yet two more tools to control the flow during loops.\n", - "\n", - "The break keyword can interrupt any loop, even if it has not yet run to completion. The code then continues running after the loop. This can be useful. Suppose we are searching a list for an entry that meets a certain condition. We may loop over the list and check each item for our desired criteria. If we find the item we are looking for, there is no need to continue searching the remainder of the list. Hence we will save time by running break.\n", - "\n", - "The statement works in both for-loops and while-loops. In the case of while loops, this means the loop can be told to run forever until break is executed." - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "What is the capital of France? Huh?\n", - "Try again!\n", - "What is the capital of France? F\n", - "Try again!\n", - "What is the capital of France? Paris\n", - "Well done!\n" - ] - } - ], - "source": [ - "while True: # True is always True, so this loop won't end until it hits a break!\n", - " answer = input(\"What is the capital of France? \")\n", - " if answer == \"Paris\":\n", - " break\n", - " else:\n", - " print(\"Try again!\")\n", - "\n", - "print(\"Well done!\") # this is not in the loop (because of the indentation!)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It also means that the \"checking\" phase of the loop, which checks whether the loop should continue running or stop and proceed to the next code block, can be placed at the beginning, middle or end of the loop, or even in multiple places. Usually a while-loop checks the condition at the beginning of the loop. But with a break, we can check at the end.\n", - "\n", - "The other control tool is continue. This keyword is again used inside a loop, and tells Python not to finish its current pass through the looped code, and instead continue to the next pass through, starting at the top again. This is syntactic sugar: a programming term which means a language element that is not strictly necessary, but makes it easier to type or express certain ideas. Virtually every continue could be replaced by re-arranging if statements, but sometimes continue just makes the whole thing easier and more readable.\n", - "\n", - "For now just pass your eyes over this toy example, and see if you can figure out what's going on:" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "H\n", - "i\n", - "P\n", - "y\n" - ] - } - ], - "source": [ - "for letter in \"Hello, we wish to learn Python\":\n", - " if letter in \"and thus, where should we go?\":\n", - " continue\n", - " else:\n", - " print(letter)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## For, else" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This is valid Python code:" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Is a strictly ascending sequence\n", - "Not strictly ascending\n" - ] - }, - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 46, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "def strictly_ascending(seq):\n", - " '''\n", - " Check whether a sequence of values is in ascending order\n", - " '''\n", - " for i, x in enumerate(seq[1:]):\n", - " if seq[i+1] <= seq [i]:\n", - " print(\"Not strictly ascending\")\n", - " break\n", - " else:\n", - " print(\"Is a strictly ascending sequence\")\n", - " return True\n", - " return False\n", - " \n", - "strictly_ascending([1, 2, 3, 6, 9])\n", - "strictly_ascending([1, 2, 3, 3])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Most programmers double-take when they see this construction, and some prefer to avoid it altogether. A for-loop can be given an else clause, that executes only in the event that the for-loop ran to completion, and did not experience a break. This can be useful when searching through a list looking for an entry meeting certain conditions.\n", - "\n", - "Again, syntactic sugar. The same code could have been written:" - ] - }, - { - "cell_type": "code", - "execution_count": 48, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Is a strictly ascending sequence\n", - "Not strictly ascending\n" - ] - }, - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 48, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "def strictly_ascending(seq):\n", - " '''\n", - " Check whether a sequence of values is in ascending order\n", - " '''\n", - " in_order = True\n", - " for i, x in enumerate(seq[1:]):\n", - " if seq[i+1] <= seq [i]:\n", - " print(\"Not strictly ascending\")\n", - " in_order = False\n", - " break\n", - " if in_order:\n", - " print(\"Is a strictly ascending sequence\")\n", - " return True\n", - " return False\n", - "\n", - "strictly_ascending([1, 2, 3, 6, 9])\n", - "strictly_ascending([1, 2, 3, 3])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Notice however, that this requires creating an extra variable to keep track of whether we found anything amiss. Which you use is up to you; I'm a fan of for-else -- sometimes it just feels like the right solution to a problem for me. Others disagree, with the belief that the construction is so peculiar to Python that it makes the code difficult to read for programmers who are not used to seeing it." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.1" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/PurePy 8. Advanced Flow Control/.ipynb_checkpoints/Advanced Flow Control-checkpoint.ipynb b/PurePy 8. Advanced Flow Control/.ipynb_checkpoints/Advanced Flow Control-checkpoint.ipynb deleted file mode 100644 index f4c0cd3..0000000 --- a/PurePy 8. Advanced Flow Control/.ipynb_checkpoints/Advanced Flow Control-checkpoint.ipynb +++ /dev/null @@ -1,728 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# More Flow Control\n", - "\n", - "So far, we have met if, elif and else, as well as for-loops and while-loops. Now we take a look at some more tools we have to control the behaviour of loops. Briefly before that though." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## The pass statement" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The statement pass is simply the \"do nothing\" statement. Including this somewhere in your code does precisely nothing. However, it is formally a valid Python statement. Therefore it can be used as a placeholder in a location where Python formally requires some code, but you either don't want to do anything, or simply haven't got round to it. For example, when you start designing a sequence of ifs and elifs, you may want to write out each possible choice ahead of writing out what to do in each case. Hence, we might write the Fizzbuzz challenge first like this:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "for x in range(100):\n", - " if x % 3 == 0 and x % 5 == 0:\n", - " pass\n", - " elif x % 3 == 0:\n", - " pass\n", - " elif x % 5 == 0:\n", - " pass\n", - " else:\n", - " pass" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This way, we can see some of the structure of the program, even we've not filled in the details yet. This is particularly useful when you are breaking your problem down into different functions; you can easily see what is yet to be done, especially when combined with doc strings." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "## example here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## More logical checking tools\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Using other types as stand-ins for Booleans\n", - "\n", - "A neat thing about Python is that if we use a non-Boolean type in a logical expression, Python will have a go at interpreting it as a Boolean anyway.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n" - ] - } - ], - "source": [ - "print(1 and 0)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1\n" - ] - } - ], - "source": [ - "print(1 and 1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this case, Python knows to use 0 as False, and 1 as True. This works for all kinds of things, but the rule of thumb is this. If you give Python numbers in a boolean expression, 0 is considered False, anything non-zero is considered True (this applies to ints, floats, and complex numbers). If you given Python a sequence or container, such as a list or string (which is a sequence of letters), then an empty sequence is considered False and a non-empty sequence is considered True:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Cat\n" - ] - } - ], - "source": [ - "print(\"\" or \"Cat\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To convert something into a boolean in the more classical sense, use the bool() function: " - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print(bool(\"\"))" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(bool(\"Cat\"))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### In\n", - "\n", - "With many sequence or container-like objects, we can check for membership using in. For example:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print('cat' in \"concatenate\")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print(\"dog\" in [\"cat\", \"dog\", \"hamster\"])" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "# this is a set, a data structure we have not discussed.\n", - "# sets contain unordered data with no duplicates\n", - "# (identical entries are counted as a single entry)\n", - "# They are occasionally useful.\n", - "print(3 in {1, 2, 3})" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Identity: \"is\"\n", - "\n", - "We can check for two objects being actually the same object in Python's memory using is. This is, confusingly, different to using ==, which checks for some equality of value. This leads to some profoundly weird cases, especially with numbers and strings. Therefore the advice is to only use this in this in the situations I outline here. Let's see examples." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], - "source": [ - "print([] is [])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Why did this evaluate False? Because writing an empty list [] always creates a brand new empty list. These are two different lists as far as Python is concerned. Hence is will come out as False. However:" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n" - ] - } - ], - "source": [ - "print([] == [])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This comes out as True. While these are different lists, they have the same contents, and Python can see this. So, we use is when we want Python to check not just that two things look similar, but are one and the same object.\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n", - "False\n" - ] - } - ], - "source": [ - "a = [\"spam\"]\n", - "b = a\n", - "c = [\"spam\"]\n", - "print(a is b)\n", - "print(c is a)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There is one more use case I have found useful. This is for checking the None type object. None is a special object, representing nothing, nada. A function that gives no return value gives None:" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "None\n" - ] - } - ], - "source": [ - "def gives_nothing():\n", - " pass\n", - "print(gives_nothing())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In many boolean situations, None is interpreted as False." - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Was interpreted as False\n" - ] - } - ], - "source": [ - "probably_false = None\n", - "if not probably_false:\n", - " print(\"Was interpreted as False\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "However, None and False are certainly not the same. If I have a function that sometimes returns a value and sometimes does not, and I want to check if the function returned None, I can use is:" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "gives_nothing() gave nothing\n" - ] - } - ], - "source": [ - "if gives_nothing() is None:\n", - " print(\"gives_nothing() gave nothing\")" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "if gives_nothing() is not None:\n", - " print(\"gives_nothing() gave something\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Looping over indices\n", - "\n", - "It is somewhat common, though to be avoided if feasible, to wish to loop over the indices of a list or other sequence, rather than the items of a list.\n", - "\n", - "There is a commonly used, naive way to do this. It is wrong, in the sense that it is ugly. Suppose I wish to print a list with numbering:" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1. Fruit\n", - "2. Coffee\n", - "3. Tofu\n", - "4. Rice\n", - "5. Soy sauce\n" - ] - } - ], - "source": [ - "shopping = [\"Fruit\", \"Coffee\", \"Tofu\", \"Rice\", \"Soy sauce\"]\n", - "## Ugly version:\n", - "for i in range(len(shopping)):\n", - " list_item = \"{}. {}\".format(i+1, shopping[i]) \n", - " print(list_item)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This is very common to see from both new and experienced programmers; in many programming languages, this kind of construction is the only way to perform this task. There is a much preferred method in Python, however:" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1. Fruit\n", - "2. Coffee\n", - "3. Tofu\n", - "4. Rice\n", - "5. Soy sauce\n" - ] - } - ], - "source": [ - "# Pythonic version\n", - "for i, grocery in enumerate(shopping):\n", - " list_item = \"{}. {}\".format(i+1, grocery)\n", - " print(list_item)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So, enumerate gives a sequence of tuples, the first being the index, the second being the element. Now we can use both. Fab!" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[(0, 'Fruit'), (1, 'Coffee'), (2, 'Tofu'), (3, 'Rice'), (4, 'Soy sauce')]\n" - ] - } - ], - "source": [ - "print(list(enumerate(shopping)))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Break and continue\n", - "\n", - "We have yet two more tools to control the flow during loops.\n", - "\n", - "The break keyword can interrupt any loop, even if it has not yet run to completion. The code then continues running after the loop. This can be useful. Suppose we are searching a list for an entry that meets a certain condition. We may loop over the list and check each item for our desired criteria. If we find the item we are looking for, there is no need to continue searching the remainder of the list. Hence we will save time by running break.\n", - "\n", - "The statement works in both for-loops and while-loops. In the case of while loops, this means the loop can be told to run forever until break is executed." - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "What is the capital of France? Huh?\n", - "Try again!\n", - "What is the capital of France? F\n", - "Try again!\n", - "What is the capital of France? Paris\n", - "Well done!\n" - ] - } - ], - "source": [ - "while True: # True is always True, so this loop won't end until it hits a break!\n", - " answer = input(\"What is the capital of France? \")\n", - " if answer == \"Paris\":\n", - " break\n", - " else:\n", - " print(\"Try again!\")\n", - "\n", - "print(\"Well done!\") # this is not in the loop (because of the indentation!)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It also means that the \"checking\" phase of the loop, which checks whether the loop should continue running or stop and proceed to the next code block, can be placed at the beginning, middle or end of the loop, or even in multiple places. Usually a while-loop checks the condition at the beginning of the loop. But with a break, we can check at the end.\n", - "\n", - "The other control tool is continue. This keyword is again used inside a loop, and tells Python not to finish its current pass through the looped code, and instead continue to the next pass through, starting at the top again. This is syntactic sugar: a programming term which means a language element that is not strictly necessary, but makes it easier to type or express certain ideas. Virtually every continue could be replaced by re-arranging if statements, but sometimes continue just makes the whole thing easier and more readable.\n", - "\n", - "For now just pass your eyes over this toy example, and see if you can figure out what's going on:" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "H\n", - "i\n", - "P\n", - "y\n" - ] - } - ], - "source": [ - "for letter in \"Hello, we wish to learn Python\":\n", - " if letter in \"and thus, where should we go?\":\n", - " continue\n", - " else:\n", - " print(letter)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## For, else" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This is valid Python code:" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Is a strictly ascending sequence\n", - "Not strictly ascending\n" - ] - }, - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 46, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "## NEEDS A BETTER EXAMPLE, THIS ONE IS ENTIRELY USELESS\n", - "\n", - "def strictly_ascending(seq):\n", - " '''\n", - " Check whether a sequence of values is in ascending order\n", - " '''\n", - " for i, x in enumerate(seq[1:]):\n", - " if seq[i+1] <= seq [i]:\n", - " print(\"Not strictly ascending\")\n", - " break\n", - " else:\n", - " print(\"Is a strictly ascending sequence\")\n", - " return True\n", - " return False\n", - " \n", - "strictly_ascending([1, 2, 3, 6, 9])\n", - "strictly_ascending([1, 2, 3, 3])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Most programmers double-take when they see this construction, and some prefer to avoid it altogether. A for-loop can be given an else clause, that executes only in the event that the for-loop ran to completion, and did not experience a break. This can be useful when searching through a list looking for an entry meeting certain conditions.\n", - "\n", - "Again, syntactic sugar. The same code could have been written:" - ] - }, - { - "cell_type": "code", - "execution_count": 48, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Is a strictly ascending sequence\n", - "Not strictly ascending\n" - ] - }, - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 48, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "def strictly_ascending(seq):\n", - " '''\n", - " Check whether a sequence of values is in ascending order\n", - " '''\n", - " in_order = True\n", - " for i, x in enumerate(seq[1:]):\n", - " if seq[i+1] <= seq [i]:\n", - " print(\"Not strictly ascending\")\n", - " in_order = False\n", - " break\n", - " if in_order:\n", - " print(\"Is a strictly ascending sequence\")\n", - " return True\n", - " return False\n", - "\n", - "strictly_ascending([1, 2, 3, 6, 9])\n", - "strictly_ascending([1, 2, 3, 3])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Notice however, that this requires creating an extra variable to keep track of whether we found anything amiss. Which you use is up to you; I'm a fan of for-else -- sometimes it just feels like the right solution to a problem for me. Others disagree, with the belief that the construction is so peculiar to Python that it makes the code difficult to read for programmers who are not used to seeing it." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.2" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/PurePy 9. Advanced Functions/.ipynb_checkpoints/9.0 Advanced Functions and Functional Programming-checkpoint.ipynb b/PurePy 9. Advanced Functions/.ipynb_checkpoints/9.0 Advanced Functions and Functional Programming-checkpoint.ipynb deleted file mode 100644 index 7ed7e1e..0000000 --- a/PurePy 9. Advanced Functions/.ipynb_checkpoints/9.0 Advanced Functions and Functional Programming-checkpoint.ipynb +++ /dev/null @@ -1,785 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this article we're gonna cover a lot of ground. So far we have seen that functions can be used to encapsulate tasks we want to perform throughout our programs. They take some input, perform some computation, and then give us an output. We're now going to explore a number of powerful concepts involving functions, culminating in a brief discussion of functional programming, a programming paradigm that is quite different to the methodology we have used so far.\n", - "\n", - "## First-class objects\n", - "\n", - "We've not got around to a proper discussion of objects yet. But they're all around us. A number is an object, a string is an object, a list is an object. Basically anything you can assign to a variable or pass to a function or get out of a function is an object.\n", - "\n", - "Well, turns out functions are objects too. You can assign functions to variables, use functions as arguments to functions, and even return functions from functions.\n", - "\n", - "We've actually briefly seen this before. In a previous video, we used the max() function to determine the maximum entry of a dictionary by value rather than by key. For this, we had to pass the get function to max, which gets the value from the key, to make the max() function behave in this way.\n", - "\n", - "Some of the concepts here will be based on this possibly surprising fact about functions.\n", - "\n", - "## Recursion\n", - "\n", - "An interesting fact about functions is that they can be called within their own definitions. This is useful for a surprising number of algorithms, and can sometimes lead to nicer code than loops. Just like with while-loops though, you have to make sure there is some point at which the functions stop calling and start returning values! This is called the \"base case\". A recursive function calls itself until it reaches the base case." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "514229" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "def fib(n):\n", - " # get the nth fibonacci number\n", - " if n == 1:\n", - " return 0\n", - " elif n == 2:\n", - " return 1\n", - " else:\n", - " return fib(n-1) + fib(n-2)\n", - " \n", - "fib(30)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The deal with recursion is that some problems are the sum of several smaller problems of the same kind. For example, a lot of searching problems, where we are searching for some item in a structure such as a file system, network or list, can be conceived of as searching through many sub-structures within that structure. For instance, searching for a file in a directory involves searching through sub-directories of that directory, which involves searching through sub-directories of the sub-directories, and so on. This complicated task can be accomplish with a recursive algorithm." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercises\n", - "\n", - "1. Look up the binary search algorithm and write a recursive function to implement it.\n", - "2. (Mathematical, challenging) Laplace's algorithm for finding the determinant of a square matrix is recursive. Write a function that can take a square matrix as a list of lists and find its determinant using the recursive Laplace algorithm." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Lambda expressions\n", - "\n", - "Functional programming is based on the formal mathematical system called the lambda calculus. A vestige of this origin lives on in so-called lambda expressions. This somewhat intimidating-sounding name is actually very simple. As one of the Python developers once said, if lambda were called \"makefunction\", no one would be confused. A lambda expression consists solely of one or more inputs, followed by a return statement. Here is a simple lambda expression that squares a number:" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - ">" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "lambda x : x**2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This is a complete description of a function. The variable x goes in, x**2 comes out. The function consists of a single return expression. There can be no variable assignments or references; the function is solely defined by input and output. The function has no name attached to it, but it can still be assigned to a variable:" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "100\n" - ] - } - ], - "source": [ - "square = lambda x : x**2\n", - "print(square(10))" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "125" - ] - }, - "execution_count": 42, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "power = lambda x, n: x**n\n", - "power(5, 3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So, why lambdas? Sometimes, it's just quicker and easier to use lambdas. Suppose I want a function that tells me the number of digits in an integer:" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "digits = lambda x: len(str(x))" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "7" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "digits(4343452)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another primary use case is for functions that take a function as an argument, but the function you want to pass is too simple to be worth building separately." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Suppose I have a list of 2d vectors, represented as pairs of numbers. The norm of a vector $(a, b)$ is given by the Pythagorean formula $\\sqrt{a^2 + b^2}$. We wish to find the vector with the largest norm." - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# first make some random vectors\n", - "from random import uniform\n", - "vectors = [(uniform(-50, 50), uniform(-50, 50)) for x in range(20)]" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(-45.3519046167027, 47.28755575244766)\n" - ] - } - ], - "source": [ - "# find vector with largest norm:\n", - "largest = max(vectors, key= lambda v: (v[0]**2 + v[1]**2)**0.5)\n", - "print(largest)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Recall that the key argument provided to the max() function tells max() what method to use to measure the maximum. It must be a function. But instead of defining the function using the normal syntax, it was quicker and easier to write a little lambda function in that argument slot. The .sort() method that can be applied to lists can also take a key argument, so lambda expressions can be useful here too. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercises\n", - "\n", - "Write a lambda function that acts as an XOR logical operator. XOR stands for \"exclusively or\", and evaluates to true only when one of its arguments is true, but the other isn't. \"One, the other, but not both\". In other words, correctly define the XOR variable using a lambda function in this example so that the code runs:\n" - ] - }, - { - "cell_type": "code", - "execution_count": 52, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n", - "True\n", - "True\n", - "False\n" - ] - } - ], - "source": [ - "#XOR = your lambda expression here\n", - "print(XOR(True, True))\n", - "print(XOR(False, True))\n", - "print(XOR(True, False))\n", - "print(XOR(False, False))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "(Challenge) Write a lambda function that returns a new lambda function for raising an input to a chosen power. Again, correctly define the following variable so that the code runs:" - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "25\n", - "125\n", - "0.2\n" - ] - } - ], - "source": [ - "# raiseto = your lambda here\n", - "square = raiseto(2)\n", - "print(square(5))\n", - "cube = raiseto(3)\n", - "print(cube(5))\n", - "invert = raiseto(-1)\n", - "print(invert(5))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## \\*args and \\**kwargs\n", - "\n", - "In the introduction to functions, we saw that we had a choice between using positional arguments, and keyword arguments.\n", - "\n", - "Sometimes we may want a function that can take arbitrary collections of arguments. For instance, the max() can take an arbitrary number of positional arguments before accepting a keyword argument:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# the abs() function gives the number's absolute value -- in this case, ignores the minus sign\n", - "print(max(1, -5, 3, 4, -2, key=abs))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Our own functions can match this behaviour, using a \\* symbol. A function parameter with a \\* at the beginning is understood to be a sequence of arguments of an unknown length." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1. Apples\n", - "2. Bananas\n", - "3. Pears\n" - ] - } - ], - "source": [ - "def number_my_sequence(*seq):\n", - " for i, thing in enumerate(seq):\n", - " print(\"{}. {}\".format(i+1, thing))\n", - " \n", - "number_my_sequence(\"Apples\", \"Bananas\", \"Pears\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There is something of an opposite notion; when calling a function, if an argument is preceded by the \\*, then if it is sequence-like, it will be \"unpacked\" before the function is called. Look carefully at the example. The adder function takes two arguments. We pass it just one argument, which is a sequence with two elements to be unpacked to form the two arguments:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "11\n" - ] - } - ], - "source": [ - "def adder(a, b):\n", - " return a + b\n", - "numbers = [5, 6]\n", - "print(adder(*numbers))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There is an equivalent syntax for keyword arguments. A \\*\\* added to the beginning of a parameter means that the keyword arguments provided here will be expanded to a dictionary:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'name': 'Sam', 'working_with': 'HiPy'}\n" - ] - } - ], - "source": [ - "def kwarg_example(**things):\n", - " print(things)\n", - " \n", - "kwarg_example(name=\"Sam\", working_with=\"HiPy\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The reverse syntax also applies as above, in that a dictionary can be expanded into keyword arguments with keys as keywords and values as arguments." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Iterators and generators\n", - "\n", - "A brief bit of theoretical woffle before we get to the upshot. You have probably noticed that for-loops can be used on many different kinds of objects, such as ranges, lists, strings, tuples, dictionaries, and many others. Objects that can be looped over are called \"iterable\". When placed in the context of a for-loop, they become an iterator, which means they know what to do each time the for-loop asks for the next item. We can actually do this manaully. Firstly, observe that at first, Python does not know what \"next\" means in terms of a string:" - ] - }, - { - "cell_type": "code", - "execution_count": 54, - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "'str' object is not an iterator", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0mpythonclub\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m\"HiPy\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mpythonclub\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;31mTypeError\u001b[0m: 'str' object is not an iterator" - ] - } - ], - "source": [ - "pythonclub = \"HiPy\"\n", - "print(next(pythonclub))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "However, we can ask the string to give us an iterator:" - ] - }, - { - "cell_type": "code", - "execution_count": 55, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "iterclub = iter(pythonclub)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can ask for the next value:" - ] - }, - { - "cell_type": "code", - "execution_count": 56, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "H\n" - ] - } - ], - "source": [ - "print(next(iterclub))" - ] - }, - { - "cell_type": "code", - "execution_count": 57, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "i\n" - ] - } - ], - "source": [ - "print(next(iterclub))" - ] - }, - { - "cell_type": "code", - "execution_count": 58, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "P\n" - ] - } - ], - "source": [ - "print(next(iterclub))" - ] - }, - { - "cell_type": "code", - "execution_count": 59, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "y\n" - ] - } - ], - "source": [ - "print(next(iterclub))" - ] - }, - { - "cell_type": "code", - "execution_count": 60, - "metadata": {}, - "outputs": [ - { - "ename": "StopIteration", - "evalue": "", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mStopIteration\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0miterclub\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;31mStopIteration\u001b[0m: " - ] - } - ], - "source": [ - "print(next(iterclub)) # we're out of letters!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So what a for-loop does is ask the object (string, list, range, etc) we provide for an iterator, and then use next on the object until it runs out.\n", - "\n", - "We'll discuss this point in more detail when we discuss object-oriented programming. But for now, in our discussion of functions, we can make a special kind of function that is iterable. In other words, the function can give a sequence of different outputs when placed in the context of a for-loop. A generator looks exactly like a normal function, but instead of the word return returning a value, the word yield is used instead. When the generator \"yields\" something, it stops until something asks it for the next value, in which case, it picks up exactly where it left off!" - ] - }, - { - "cell_type": "code", - "execution_count": 67, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "from random import randint # for random integers\n", - "def random_numbers(count, low=0, high=100):\n", - " for i in range(count):\n", - " yield randint(low, high) " - ] - }, - { - "cell_type": "code", - "execution_count": 68, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Next number is 68\n", - "Next number is 72\n", - "Next number is 88\n", - "Next number is 0\n", - "Next number is 47\n", - "Next number is 36\n", - "Next number is 73\n", - "Next number is 52\n", - "Next number is 95\n", - "Next number is 3\n" - ] - } - ], - "source": [ - "for x in random_numbers(10):\n", - " print(\"Next number is\",x)\n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The enumerate() function we met in the previous article on Flow Control is somewhat equivalent to:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1. Chickpeas\n", - "2. Onions\n", - "3. Flatbread\n" - ] - } - ], - "source": [ - "def fake_enumerate(seq):\n", - " for i in range(len(seq)):\n", - " yield i, seq[i]\n", - " \n", - "shopping = [\"Chickpeas\", \"Onions\", \"Flatbread\"]\n", - "\n", - "for k, grocery in fake_enumerate(shopping):\n", - " print(\"{}. {}\".format(k+1, grocery))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Notice, inside the generator there is a for-loop, but one that can be put on pause until the outer for-loop (for k, grocery in fake_enumerate(shopping):) asks it to carry on. This is quite mindbending, but it can be useful. In the example, we use a generator to convert some real genetic data from a text file into a more Python-friendly format." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkz\nODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2MBERISGBUYLxoaL2NCOEJjY2NjY2NjY2Nj\nY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY//AABEIAWgB4AMBIgACEQED\nEQH/xAAbAAEAAwEBAQEAAAAAAAAAAAAAAgMEAQUGB//EAEUQAAIBAwIDBgQEBAMGBQQDAAECAwAE\nERIhEzFBBRQiUWFxMoGRoQYVI7E0QnLBJNHwM1JTYpLhNUOisvElY4LCVHPS/8QAFwEBAQEBAAAA\nAAAAAAAAAAAAAAECA//EACARAQACAQQDAQEAAAAAAAAAAAABERICEyExAyJhQVH/2gAMAwEAAhED\nEQA/APz+lKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUC\nlKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUC\nlKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUC\nlKUClKUClKUClKUClKUClaBZysQBpyRnnXWsZkGWAA96tSzlDNStIspiSAASPKuGylBAOBnlSpMo\nZ6VpWxmbkM9K4LOUgnbY4pUmUM9K0mymUZOAKCxmJIABI50qTKGalaO5y5I2yBk+lBZTHkufrSpM\noZ6Vf3SXfltzqRsZhzFKkyhmpV/dJNIbbBOM1zuz+a0qTKFNKu7s/mtO7P5rSpMoU0q7uz+a07s/\nmtKkyhTSru7P5rTuz+a0qTKFNKu7s/mtO7P5rSpMoU0q7uz+a07s/mtKkyhTStadm3LoGVMq3I+d\ncWwncqFUHVnT61FyhlpWprCdQSwAA570awnUgMFBIyN6JlDLSth7MuQuSgx55qtbOV/hwceVI56M\noZ6VpaxmUgMACa4LKUjIxj3q1JlDPStPcZsgYGTyrgspiSABkc6VJlDPStBs5VODgGpHs+4AJKgA\nUqTKGWlaVsZmAIAINc7nLnHhz70qTKGelaDZyg42z5UNlMDggZxmoZQz0q/ukm3LflUu4zaguBqI\n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\nv4c/jJ/6F/evLwcZwa9T8Ofxk/8AQv70GOOzjaBWN/pJjZivFGz7aRj2/auNBHxl4sszqJVTPHHh\nXo/L1+VeM/xn3rmDQh7C20fdFlS4kZiC3AEwBGD4d/Qb/KgW1aVkWaaPxIuvjA7MN+npivHIIqaw\nSNHrC+Hc5zQevLHbx5SSSUvofUBcZHhGw5epqxbGIIc9pEalTIEo3bPj+nOvApQe7HbBYQ4upUkD\ns3AE4znBxv57HeoLHDFqHeJlLKgEomGGBO+3kPL0rxaUHti3xccJL94AhBYcTVg42I5dNvTFZYjm\nC6kSWYSRRjL69idWCPbevOrupgpUE6TzGaCwXM4QpxpNJ5jUcGpC8uRyuJRzHxnrzqilBct1cKML\nPIBkHZj0p3u4/wCPL1/nPXnVNKC43VwSCZpDpGB4jt/rFO93Acvx5dR66zmqaUFhuJmI1SucYxlj\ntjlUmu7hgQ08pydRy55+dU0oLu93GnHHlxjTjWeXlXDczF2cyyam5nUcmqqUFouZxymk55+I866t\n1cIAFnkUA5ADHY1TSguN3cHTmeQ6TkeI7VwXM4IImkBHLxHaqqUF3e7n/jy9f5z15/WuNcTOQWlk\nYjGCWO2OVVUoLUuZ41CpNIoXOAGIxnnXTdTnGZpDgaR4jsPKqaUFq3MyuHWWQMNgQxyK9z8IMW7S\nlLEk8NRv/UK+er3/AMH/APiEv9A/9woM8PaoiRo3y40hMY5DIz+1X/nFmHVkt8ENn4V5Yx5V4ROS\nTXKlLb3k7VsBCVNvlsbZUVFu1rQumm3AUHLZQZIrw6Uot69x2hZyxoqQmMrncDc+9W3HadmQzQR6\nXDeA6cYGc5/YV4dKUW9W27SjiuTNJqYkHOOuavuu1rS6RVKOmnGCPv8AvXh0pRb17TtG3tblnwzp\nggedaF7cgCYaIudIB1cjivApSi3sRdpWy3jSyxtMjDk/OuN2nAdQEQUaQFwg2Ix/3ryKUot735za\ntIS8AZeIXAKDqKzXXaFvME4cQj0+Q58v+9eVSlFtveY/M/SneY/M/SsVKqNveY/M/SneY/M/SsVK\nDb3mPzP0p3mPzP0rFSg295j8z9Kd5j8z9KxUoPc/N7fg8L9Ugx6MHz86Qdq21uNKGUqHJ9xgj5V4\ndKlLbc11EWJGQCeVc7zH5n6VipVRt7zH5n6VbbX0MM6SMCwU5x69K82lB7T9q27E4VwCjrj3OR+9\nbPwy6yXVwV5aF/evma29mdpzdmPI0KRuXAB1gnH0IoKnlUZUrnGRvXbadYWVmGdLZx57VnJySfOu\nVKhnGKpfPKsjZXON9jvipI8fBXMgBVGGnBzvms1KscLEUUpSilKUoFKUoFKUoFKUoFKUoFKUoFKU\noFKUoFKUoFKUoFKUoFe/+D//ABCX+gf+4V4FbezO0pezJ2lhSNywxiQEjnnoR5UGKlKUClKUClKU\nClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKU\nClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKU\nClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKU\nClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKU\nClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUH//Z\n", - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from IPython.display import YouTubeVideo\n", - "YouTubeVideo(\"M-brh-eFgyE\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Functional Programming\n", - "\n", - "Here, we will just introduce the very basic concept of functional programming, as something to chew over and consider in your own program designs. So far, what we have been doing is what is called imperative programming. The program has a state, which means it holds some things in memory, usually in the form of variables, and we proceed by updating the program's state by changing these variables, reassigning them, and so on. At the top of this article, we used recursion to find the $n$th fibonacci number. Let's now do it in a pure imperative style:" - ] - }, - { - "cell_type": "code", - "execution_count": 69, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "514229\n" - ] - } - ], - "source": [ - "n = 30\n", - "for k in range(n):\n", - " if k < 2:\n", - " x = 0\n", - " y = 1\n", - " else:\n", - " # to understand this line, remember that when assigning variables\n", - " # the right hand side is fully evaulated before being assigned to the LHS\n", - " x, y = y, x + y\n", - "print(y)\n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This program achieves the same task, but we first set n to something. Then we iterate over k, and for each k, update two variables x and y. At each pass through the loop, the state of the program is changed; k, x, and y are all modified\\*. That is imperative programming in a nutshell." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "While imperative programming is easy to get going with, it's also easy to get in a tangle with. Because different functions are constantly referring to and altering different parts of a (large) program's state, it's very easy for errors to occur because some part of the program's state is wrong at the time a particular function or operation is executed.\n", - "\n", - "Functional programming aims to fix this by encouraging a very different style of design. Functional programming demands that we make our functions behave like mathematical functions, in that there is one, and only one, possible output for each input to a function. In imperative programming, the function may behave differently at different times with the same inputs, because the program's state is different at those different times. Moreover, the function may alter the program's state, which can cause other functions to behave differently at a later time. This is the concept of \"side-effects\".\n", - "\n", - "In functional programming, the program does not have a state. It has functions, which behave in exactly the same way every time they are called with the same inputs, guaranteed. Each function has an input, and an output, and nothing that goes on inbetween can have any effect on, or be affected by, the rest of the program's behaviour. Check out the recursive fibonacci program; there's not a variable in sight. Just functions taking inputs and returning values. This leads to essentially bug-free code, so long as the functions are correctly defined and applied in the correct order. \n", - "\n", - "Functional programming isn't easy, but Python does have some support to make it easier via the functools module. While some programming languages are purely functional, Python is multi-paradigm, and the good thing about functional programming in Python is it needn't be all or nothing. It can fit around the rest of your program design. After all, the whole point of functional programming is \"no side effects\"! Thus if you find that you can solve one of your problems by writing a function that neither affects nor is affected by the program's state, but only by its input values, then why not go ahead and do it that way, reaping some of the benefits of functional programming as you do?\n", - "\n", - "For some specific examples of functional programming techniques in Python, see this article https://maryrosecook.com/blog/post/a-practical-introduction-to-functional-programming\n", - "Note that the examples are in Python 2, which means print() does not need the brackets. Also, the author uses map(), filter a lot; in Python 3 it is generally considered preferable to use list comprehensions to perform the same task.\n", - "\n", - "\\* This is a subtle point about for-loops easily missed. The variable that gets bound at the start of each pass through, such as the x appearing in the line for x in range(10), remains assigned even after the loop is finished running. Therefore, as far as functional programming goes, it constitutes a side-effect -- the state of the program is changed. The same is not true of the \"for loops\" found in list comprehensions; these are side-effect free." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.1" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/[BASICS] Getting Started With Python 1 - The Basics/.ipynb_checkpoints/Getting Started In Python 1 - The Basics-checkpoint.ipynb b/[BASICS] Getting Started With Python 1 - The Basics/.ipynb_checkpoints/Getting Started In Python 1 - The Basics-checkpoint.ipynb deleted file mode 100644 index b88f08c..0000000 --- a/[BASICS] Getting Started With Python 1 - The Basics/.ipynb_checkpoints/Getting Started In Python 1 - The Basics-checkpoint.ipynb +++ /dev/null @@ -1,618 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![title](banner.png)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Congratulations on getting set up with Python! If you're not familiar with programming then don't worry; you have already done the hardest part. Python is one of the easiest programming languages to get into due to simple syntax (how your code is written), and a highly active community (hello!) - but can be built upon extensively to perform complex data analysis, create websites, and automate typically difficult jobs to be done quickly and efficiently.\n", - "\n", - "In this guide we're going to go over some critical programming concepts to understand, and then move onto creating a simple graph using a library we'll spend a lot of time with - matplotlib. Let's go!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Programming Basics" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To start, we need to talk very generally about objects. An object can be generally be thought as a piece of information, such as a number, word, or sentence. Later on we'll see some more complex examples of objects (and eventually how to define our own!) but for now let's look at some simple ones. Since sometimes we want to store an object in our computer's memory to recall later, we can assign an object a label. We call this label a variable." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "myVariable = 30" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To recall this variable's value, we can use the print function:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "30\n" - ] - } - ], - "source": [ - "print(myVariable)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Variables are especially helpful when the object we want to asign them to are very large. Imagine having a dataset of millions of values; it would be very fustrating to write it all out again and again! Another important property of variables is they act just like the object they were assigned to." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "apples = 4\n", - "oranges = 6" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "10\n" - ] - } - ], - "source": [ - "print(apples + oranges)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can assign any object to a variable - since the sum of our two variables above is an object (a number), we can assign it a name." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "fruits = apples + oranges" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "10\n" - ] - } - ], - "source": [ - "print(fruits)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "So far, we've only looked at whole numbers being stored as variables. In Python, these are called integers or int. For any variable, we can check the type by using the type() function:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], - "source": [ - "print(type(fruits))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Later we'll see how to define our own types, but let's look at some of the more common ones. First off we have floating point numbers." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "6.283\n" - ] - } - ], - "source": [ - "myFloat = 3.1415\n", - "\n", - "print(myFloat * 2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We also have strings, which are just characters, words, or phrases:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello Python!\n" - ] - } - ], - "source": [ - "myString = \"Hello Python!\"\n", - "\n", - "print(myString)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It's worth noting that every type has it's own attributes - we can't add two words the same way we can numbers, but Python treats adding two strings together by joining them:" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello Python! Hello World!\n" - ] - } - ], - "source": [ - "print(myString + \" Hello World!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we have Boolean or Bool variables. These can either be True or False. These are seen everywhere, most of the time behind the scenes, but it's important to know how they work as we can often use them to do some sneaky tricks to improve our code." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "myBool = True" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, for now, we have lists. Lists contain elements, that in themselves are objects:" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "myList = [1, 3.24, \"string\", False]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To pull out items from our list, we use indexing:" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "3.24\n" - ] - } - ], - "source": [ - "print(myList[1])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Indexing starts at 0, so the index 1 here takes the second element out of our list. Although this might seem unintuitive (and is a source for a lot of my errors!), there are a lot of good reasons for doing this - " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can also take slices from the list, to form new lists:" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[1, 3.24, 'string']\n" - ] - } - ], - "source": [ - "myList2 = myList[0:3]\n", - "print(myList2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Slices start at the first index, and end before the last index. Again, confusing and annoying at first, but sometimes we can use it in tricky ways to speed code up." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Like, strings, lists have some unique attributes - one example is the append() method, and more can be found in the Python documentation [here](https://docs.python.org/3/tutorial/datastructures.html). The append method is simple, it takes whatever's in the brackets and adds it to the list in question:" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[1, 3.24, 'string', False, True]\n" - ] - } - ], - "source": [ - "myList.append(True)\n", - "print(myList)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To check the length of a list, we use the len() function:" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5\n" - ] - } - ], - "source": [ - "print(len(myList))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, let's go back and take a look at some operators we missed. +, -, *, / work as expected, but it's helpful to know some others. ** is for powers, // for floor division, or division without remainder, and % for modulo, or division with just the remainder:" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "9\n", - "2\n", - "1\n" - ] - } - ], - "source": [ - "print(3 ** 2) # 3 Squared\n", - "print(5 // 2) # 5 divided by 2 without remainder\n", - "print(13 % 3) # The remainder of 13 divided by 3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Importing Modules" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Python comes with loads of functions, and we've already seen some (print, len), but sometimes we want to do more complicated things. The great thing about Python is its huge community creating tools for everyone to use. These tools usually come in packages called modules or libraries, that we can download and import to Python. If you're using Anaconda, or Azure Notebooks, almost all of the modules we use come pre-installed, so all we need to do is import them. To do this, we use the syntax:" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "import matplotlib" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To use a fuction from matplotlib, a graphical plotting library, we would have to type matplotlib.pyplot.plot(). However, as this is a bit long-winded, Python lets us shorten these names and import them under an alias as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, instead of typing matplotlib.pyplot.plot(), we just need to type plt.plot(). Let's look at how we can use matplotlib to create some simple visualisations." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First, we need some data. For this we are going to create two lists - one of the numbers 1 to 10, and another of their squares: " - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "x = [1,2,3,4,5,6,7,8,9,10]\n", - "y = [1,4,9,16,25,36,49,64,81,100]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Plotting of these is simple - we just run the plot function above with x and y as inputs, or arguments, and then use the plt.show() function to show the plot:" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(x,y)\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Great! Later on we will see how to edit these graphs, adding titles, labels to the x and y axis, and changing the color of the line and background." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For now, that's it! In the next guide we'll look more into the programming side of things - how we can write code to automate boring tasks, and create the building blocks to make bigger programs." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Worked Example" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this section, we'll look at a full piece of sample code, and explain it. Feel free to edit this and see what happens!\n", - "\n", - "Here we are looking at the stock price of Apple over Feburary 2017.\n", - "\n", - "First we import the required library, then set up our data, and finally, plot it." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\nlgeoR7cAAAAASUVORK5CYII=\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "prices = [128.750000, 128.529999, 129.080002,130.289993,131.529999,132.039993,132.419998,132.119995,133.289993,135.020004,135.509995,135.350006,135.720001,136.699997,137.110001,136.529999,136.660004,136.929993,136.990005]\n", - "days = [1,2,3,6,7,8,9,10,13,14,15,16,17,21,22,23,24,27,28]\n", - "\n", - "plt.plot(days,prices)\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Mini Project" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In this section, we'll give you something to do, to give you some practice if needed. Similar to the worked example, here's the data for the mean temperature in celsius each month over 2016 - can you graph it using matplotlib?" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "temperatures = [4.5,3.9,5.3,6.5,11.3,13.9,15.3,15.5,14.6,9.8,4.9,5.9]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.6" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/[BASICS] Getting Started With Python 2 - The Basics/.ipynb_checkpoints/Getting Started With Python 2 - The Basics-checkpoint.ipynb b/[BASICS] Getting Started With Python 2 - The Basics/.ipynb_checkpoints/Getting Started With Python 2 - The Basics-checkpoint.ipynb deleted file mode 100644 index b18a219..0000000 --- a/[BASICS] Getting Started With Python 2 - The Basics/.ipynb_checkpoints/Getting Started With Python 2 - The Basics-checkpoint.ipynb +++ /dev/null @@ -1,685 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![title](header.png)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Python as a Programming Language" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So far we've seen Python do some very simple things, that software like Excel could do just as well. What sets Python apart from other programming languages and software is it's ability to easily make automated programs quickly. Here we will look at the building blocks of writing programs, and think about how we can use them in a real environment." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## A Deeper Look Into Functions" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Functions are an integral part of Python - throughout your time with Python you will use many functions written by other people, and hopefully some you write yourself. A function can take in arguements as inputs, then performs a process, and then returns an output. Let's take a look at the pow() function to see what's going on:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "81\n" - ] - } - ], - "source": [ - "print(pow(3,4))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The pow() function takes in two arguements, and returns the first arguement to the power of the second. Let's take a look at how to write this function ourselves:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "def myPow(a,b):\n", - " return a ** b" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The most important thing to remember here is the whitespace between the left margin and the second line; Python cares about indentations. In function definitions, we declare the name and arguements of a function, and then write the process, and what to return in an indented block. The names of the arguements don't matter - they are just dummy variables, used to give Python an example of what to do." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You might have noticed instead of printing you can just output the variable straight away:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a = 3\n", - "a" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What does this have to do with functions? The number one problem with function definitions is not knowing the difference between return and print. A function can only \"return\" one thing - when the function returns something, it ends, because the output has been reached. A function can \"print\" as many things as it wants - but won't treat these as outputs. This can lead to some interesting errors - let's look at what happens when we chain functions together written with print:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "def myAdd(a,b):\n", - " print(a + b)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "8\n" - ] - } - ], - "source": [ - "myAdd(3,5) #Nothing looks wrong here, right?" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "8\n" - ] - }, - { - "ename": "TypeError", - "evalue": "unsupported operand type(s) for +: 'NoneType' and 'int'", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mmyAdd\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmyAdd\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m5\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m5\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;31m#Oops\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;32m\u001b[0m in \u001b[0;36mmyAdd\u001b[1;34m(a, b)\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mmyAdd\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;31mTypeError\u001b[0m: unsupported operand type(s) for +: 'NoneType' and 'int'" - ] - } - ], - "source": [ - "myAdd(myAdd(3,5), 5) #Oops" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With return, we don't have this problem:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def myAdd(a,b):\n", - " return a + b" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "myAdd(myAdd(3,5),5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\"Outputs\" are helpful results of functions that actually mean something - \"Prints\" are just visuals to help you out!\n", - "\n", - "In short, if your function doesn't return anything, there's probably a problem!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## If Statements" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Sometimes when writing a program we want Python to make choices for us depending on the input. If statements are usually used in a context with variables that change, for example functions. Let's look at the syntax with a simple function that tests if the input is 10 or not:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def isTen(number):\n", - " \n", - " if number == 10:\n", - " \n", - " return \"Yes!\"\n", - " \n", - " else:\n", - " \n", - " return \"No!\"\n", - " \n", - "print(isTen(10))\n", - "print(isTen(5))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Some important things here - first off the indents again; if statements, like function definitions, need whitespace for Python to understand the code. Secondly, notice that when we construct the condition (number == 10), it's a double equals sign instead of a single. This is because the single equals is already used for setting variables. There are many conditionals we can use (for example: <, >, <=, >= are less than, greater than, less than or equal to, greater than or equal to) - make sure to check out the Python documentation [here](https://docs.python.org/3/) to see examples of more." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Not all questions are Yes or No - and Python has a way for us to deal with this - elif. For example, say we want to write a program that tells us if a number greater than 5 or less than or equal to 3:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def fiveOrThree(number):\n", - " \n", - " if number > 5:\n", - " \n", - " return \"This is a big number!\"\n", - "\n", - " elif number <= 3:\n", - " \n", - " return \"This is a small number!\"\n", - " \n", - " else:\n", - " \n", - " return \"I don't know how big this number is!\"\n", - " \n", - "print(fiveOrThree(2))\n", - "print(fiveOrThree(5))\n", - "print(fiveOrThree(6))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another helpful conditional to use is in, usually used with lists:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "fruit\n", - "vegetables\n", - "unknown\n" - ] - } - ], - "source": [ - "fruits = [\"banana\", \"orange\", \"strawberry\"]\n", - "vegetables = [\"carrot\", \"potato\", \"broccoli\"] # Note: not extensive lists of fruit or vegetables\n", - "\n", - "def fruitOrVeg(food):\n", - " \n", - " if food in fruits:\n", - " \n", - " return \"fruit\"\n", - " \n", - " if food in vegetables:\n", - " \n", - " return \"vegetables\"\n", - " \n", - " else:\n", - " \n", - " return \"unknown\"\n", - " \n", - "print(fruitOrVeg(\"banana\"))\n", - "print(fruitOrVeg(\"carrot\"))\n", - "print(fruitOrVeg(\"soup\"))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loops" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There are two types of loop we'll look at here - the for loop and the while loop. Loops are used to do something simple over and over again to stop us from doing it. For example, say (for some reason) we don't know if the numbers 0 through 10 are bigger than 5 or smaller than 3. Using our function from earlier we can do the following:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for number in range(11): #range(11) gives us a list of the numbers 0-10\n", - " \n", - " print(fiveOrThree(number))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The for loop executes the indented code for every element in the list range(11)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "While loops are slightly diffent - they check for a condition before executing the indented code. For example, a way of rewriting the code above would be:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "number = 0\n", - "while number <= 10:\n", - " print(fiveOrThree(number))\n", - " number += 1 #Shorthand way of saying number = number + 1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally with loops, sometimes we want to stop the loop prematurely to save time, or when we get what we want. Firstly, let's look at an example that finds the numbers from 2 to 20 that are not prime. A prime number is a number that's only divisible by itself or 1 - so any non-prime number will be divisible by a number from 2 to n. We just need to find what these are:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4 is not prime\n", - "6 is not prime\n", - "8 is not prime\n", - "9 is not prime\n", - "10 is not prime\n", - "12 is not prime\n", - "14 is not prime\n", - "15 is not prime\n", - "16 is not prime\n", - "18 is not prime\n" - ] - } - ], - "source": [ - "for number in range(2, 20):\n", - " \n", - " for x in range(2, number): #iterates from 2 to our number\n", - " \n", - " if number % x == 0: #this means our number is divisible f\n", - " \n", - " print(str(number) + \" is not prime\")\n", - " break\n", - "\n", - "\n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Can we do better than this? What if we want to find what the number's prime factors are? Here's some code that puts all we've learnt together:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "number = 12847\n", - "primes = []\n", - "test = 2\n", - "\n", - "while True: #Sets up a loops that never ends unless we break it:\n", - " \n", - " if number == 1: #This will be clear later\n", - " \n", - " print(\"Decomposition found!\")\n", - " print(primes)\n", - " break #Finishes program\n", - " \n", - " elif number % test == 0: #If the number is divisible by the test number\n", - " \n", - " primes.append(test) #Adds the prime factor to the primes list\n", - " number /= test #Shorthand for number = number / test\n", - " \n", - " else: \n", - " test += 1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's look at this in more detail - we set up our number, an empty list for the primes, and the test number 2. We then set up an infinite while loop that will only end if we break it, then ask if the number has been fully decomposed into its factors. If this is the case, we print the decomposition and break out of the loop, ending the program. If this isn't the case, we check to see if our test number divides our number. If this happens, we add our test number to the list, and divide our number by the test number. If neither of these conditions are met, we just add 1 to the test number and try again. Eventually, the number will keep being divided by prime numbers and reach 1, at which point the program ends.\n", - "\n", - "At first glance this program may seem complicated, don't worry! Break it down into parts and see if you can understand each bit, then put it all together - once you've done that, try turning this into a function so we can input what \"number\" is.\n", - "\n", - "Similarly, if this program seems a bit wasteful - you're right! We could turn this into a function to generalise it more, or use better syntax in places to speed the program up. Programming is more of art than a science - there are many \"right answers\"!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Another Look At Methods" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We've already seen a method in the last guide, namely the append method. Let's talk about them a bit more to get comfortable with them, as we'll see them pop up everywhere.\n", - "\n", - "Strings in Python can act as lists - we can iterate over them using for loops, as well as perform some unique methods on them. For example, we can make a string into all upper case using the .upper() method:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "string = \"hello python!\"\n", - "print(string.upper())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Similarly, there are some methods for lists:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "myList = [\"Tom\",\"Andy\",\"Pete\",\"Josh\"]\n", - "\n", - "print(myList.index(\"Andy\")) #Gives us the index of Andy\n", - "print(myList.pop()) #Gives us the last element and removes it\n", - "print(myList) #Gives us the list back, with the last element popped out." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Dictionaries" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Dictionaries are our first real example of a data structure. They let us assign values to custom indexes:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "HiPy = {\"location\": \"Liverpool University\", \"startDate\": 2016, \"language\": \"Python\"}" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To get our entries back out of the dictionary we index as if it were a list with custom indexes:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "HiPy[\"location\"]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Dictionaries can help us manage data more intuitively at the price of using more memory. For example, if we wanted to store the marks of three students, we could use a list of lists, which is hard to read: " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "marks = [[90,86,70],[60,70,65],[90,40,60]]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Or use a list of dictionaries:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Adam = {\"maths\": 90, \"english\": 86, \"science\":70}\n", - "Billy = {\"maths\": 60, \"english\": 70, \"science\":65}\n", - "Chris = {\"maths\": 90, \"english\": 40, \"science\":60}\n", - "\n", - "students = [Adam, Billy, Chris]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can reference everything from the students list, or reference things directly from the students in a more intuitive way:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(Adam[\"maths\"])\n", - "print(Billy[\"science\"])\n", - "print(students[1][\"english\"])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Worked Example" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's take a look at a program that outputs the first n numbers of the fibonacci sequence:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def fib(n):\n", - " a = 1\n", - " b = 1\n", - " fibList = [1,1]\n", - " \n", - " while len(fibList) < n:\n", - " b = a + b\n", - " a = b - a #Shuffles the numbers around so we get the next pair\n", - " fibList.append(b)\n", - " \n", - " return fibList\n", - "\n", - "print(fib(10))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As with our prime example before, we set up our variables, then a while loop that checks to see if we've reached the nth fibonacci number yet. If it hasn't, we generate the next in the sequence and add it to the list. If it has, we return the list and finish the program. \n", - "\n", - "There are many ways of improving this program, including using indexing, or simultaneously declaring what a and b are in the while loop - however this code works well enough for now." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Mini Project" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For a long time, the number one programming challenge for programmers hoping to work at big tech companies was the \"FizzBuzz\" challenge. It involves making a program that given a number, returns Fizz if divisible by 3, and Buzz if divisible by 5, and FizzBuzz if divisible by both. Can you:\n", - "\n", - "* Make a function that does this?\n", - "* Set up a for loop that runs this function on the numbers 1-100?\n", - "* Using the map funciton, do the same as above, but without using a for loop?" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.6" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/[BASICS] Numpy and Pandas/.ipynb_checkpoints/Numpy and Pandas-checkpoint.ipynb b/[BASICS] Numpy and Pandas/.ipynb_checkpoints/Numpy and Pandas-checkpoint.ipynb deleted file mode 100644 index e3bae59..0000000 --- a/[BASICS] Numpy and Pandas/.ipynb_checkpoints/Numpy and Pandas-checkpoint.ipynb +++ /dev/null @@ -1,788 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![title](header.png)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Why Numpy and Pandas?" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For a long time, Python programmers who worked with data had to use the core Python libraries for importing, organising and manipulating data. The modules Numpy and Pandas give us tools we can use to work with data quickly and efficiently in a nicer format. By the end of this guide you should feel comfortable with Numpy arrays and Pandas series and dataframes." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Introduction to Numpy" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Numpy is a module that lets us generate more efficient lists that have the option to be multi-dimensional (stacked inside each other). Before we look at what Numpy can do, we have to first import the module. As with matplotlib, we will be importing it under a different name for brevity. Here we use \"np\"." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Almost all of Numpy's functionality comes from it's multi-dimensional arrays, which mostly operate like Python lists, but use less memory, have better performance and have some other cool features under the hood. To initialise an array, we use the function np.array:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[1 2 3 4]\n" - ] - } - ], - "source": [ - "a = np.array([1,2,3,4])\n", - "print(a)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A very important note is that the \"np.array\" function's argument is a list - Python won't understand you if you give it something else! For example - the command..." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "ename": "ValueError", - "evalue": "only 2 non-keyword arguments accepted", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0maError\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marray\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m4\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;31mValueError\u001b[0m: only 2 non-keyword arguments accepted" - ] - } - ], - "source": [ - "aError = np.array(1,2,3,4)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "... give us an error because Python expects a list, not four numbers.\n", - "\n", - "We can also make two dimensional arrays like so (note the nested brackets):" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[1 2 3 4]\n", - " [5 6 7 8]]\n" - ] - } - ], - "source": [ - "a = np.array([ [1,2,3,4] , [5,6,7,8] ])\n", - "print(a)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Numpy also comes with some functions to generate arrays - for example the function linspace() gives us an array of numbers equally spread out between the arguements. For example:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ 0. 0.5 1. 1.5 2. 2.5 3. 3.5 4. 4.5 5. 5.5 6. 6.5\n", - " 7. 7.5 8. 8.5 9. 9.5 10. ]\n" - ] - } - ], - "source": [ - "b = np.linspace(0,10,21)\n", - "print(b)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Gives us an array of 21 elements equally spaced from 0 to 10 (because we include endpoints here we have to be careful about how many numbers we want!)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Numpy, unlike Python lists, can have operations performed on them directly:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ 0. 0.25 1. 2.25 4. 6.25 9. 12.25 16. 20.25\n", - " 25. 30.25 36. 42.25 49. 56.25 64. 72.25 81. 90.25\n", - " 100. ]\n" - ] - } - ], - "source": [ - "print(b**2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can also use numpy arrays in the same way as Python lists for graphing (in fact this is recommended):" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt #We need to import our graphing library!\n", - "\n", - "plt.plot(b,b**2)\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Numpy arrays can also be indexed, sliced and iterated over in the same way as Python lists can:" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0.0\n" - ] - } - ], - "source": [ - "print(b[0])" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[0. 0.5 1. 1.5 2. 2.5 3. 3.5 4. 4.5 5. ]\n" - ] - } - ], - "source": [ - "print(b[0:11])" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0.0 is an element of our array!\n", - "0.5 is an element of our array!\n", - "1.0 is an element of our array!\n", - "1.5 is an element of our array!\n", - "2.0 is an element of our array!\n", - "2.5 is an element of our array!\n", - "3.0 is an element of our array!\n", - "3.5 is an element of our array!\n", - "4.0 is an element of our array!\n", - "4.5 is an element of our array!\n", - "5.0 is an element of our array!\n", - "5.5 is an element of our array!\n", - "6.0 is an element of our array!\n", - "6.5 is an element of our array!\n", - "7.0 is an element of our array!\n", - "7.5 is an element of our array!\n", - "8.0 is an element of our array!\n", - "8.5 is an element of our array!\n", - "9.0 is an element of our array!\n", - "9.5 is an element of our array!\n", - "10.0 is an element of our array!\n" - ] - } - ], - "source": [ - "for element in b:\n", - " print(str(element) + \" is an element of our array!\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Apart from direct operations on arrays - this may seem a little redundant. So why do we use Numpy arrays over Python lists? Well, most scientific libraries leverage numpy for better performance. Better performance and a smaller memory footprint might not sound impressive now but imagine if you would work on a dataset with billions of entries; then these things become very important!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Pandas" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Numpy is the backbone of most data focused Python libraries, because it provides a solid foundation to build upon. One of the most important of these libraries is Pandas, which we use to create series and dataframes, i.e tables.\n", - "\n", - "As always, we first need to import the library. With pandas we use the alias \"pd\" by convention:" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "Pandas' functionality is two Python objects - the series, and the dataframe. For making series, we can use the Series function (note: this is case sensitive!):" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0 1\n", - "1 1\n", - "2 2\n", - "3 3\n", - "4 5\n", - "5 8\n", - "dtype: int64\n" - ] - } - ], - "source": [ - "c = pd.Series([1,1,2,3,5,8])\n", - "print(c)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The numbers in the left column are our index - it can be helpful to change this, for example if our data is time based. To do this, we add another arguement to the series function:" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Monday 1\n", - "Tuesday 1\n", - "Wednesday 2\n", - "Thursday 3\n", - "Friday 5\n", - "Saturday 8\n", - "dtype: int64\n" - ] - } - ], - "source": [ - "c = pd.Series([1,1,2,3,5,8], index=[\"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"])\n", - "print(c)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Dataframes are just a collection of series. To make a dataframe, we have a few options, all using the DataFrame function (again notice the capitals!).\n", - "\n", - "We can pass a two dimensional numpy array as an arguement, along with column names (here we use the random sublibrary of numpy to give us a 6x4 array of random numbers):\n", - "\n", - "(Note: here np.random.randn(x,y) gives us an x by y numpy array with random entries)" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " A B C D\n", - "0 -1.304458 0.128916 0.917312 -0.830153\n", - "1 -2.312278 -0.631357 -0.524241 -1.663592\n", - "2 -1.527491 -0.136707 -1.041927 -0.649112\n", - "3 0.621613 0.384033 -0.529702 1.046160\n", - "4 0.603338 -1.430888 -1.414519 0.308135\n", - "5 1.281230 -0.966232 0.618242 1.862749\n" - ] - } - ], - "source": [ - "d = pd.DataFrame(np.random.randn(6,4), columns=['A','B','C','D'])\n", - "print(d) #Note, if you are using jupyter notebook, just outputting d here instead of printing it will give you a nicer format." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Another way is to pass a dictionary as our arguement to the function - here we use the function \"pd.date_range\" to generate an array of dates, starting from 30/03/2017 and ending at 02/04/2017:" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " A B C\n", - "0 1 hello 2017-03-30\n", - "1 2 hello 2017-03-31\n", - "2 3 hello 2017-04-01\n", - "3 4 hello 2017-04-02\n" - ] - } - ], - "source": [ - "e = pd.DataFrame({'A': [1,2,3,4], 'B':\"hello\", 'C': pd.date_range('20170330', periods=4)})\n", - "print(e)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Most of the time during data analysis, we will looking at tables that are much larger than just 4 or 5 rows. It can be helpful to know some commands to give us summary information about our data without bringing up the whole frame.\n", - "\n", - "The head and tail methods give us the first and last row(s) of the frame:" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " A B C D\n", - "0 -1.304458 0.128916 0.917312 -0.830153\n", - "1 -2.312278 -0.631357 -0.524241 -1.663592\n", - "2 -1.527491 -0.136707 -1.041927 -0.649112\n" - ] - } - ], - "source": [ - "print(d.head(3)) #Looks at the first 3 rows of our \"d\" dataframe" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " A B C\n", - "3 4 hello 2017-04-02\n" - ] - } - ], - "source": [ - "print(e.tail(1)) #Looks at the last row of our \"e\" dataframe" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The describe method can give us some summary statistics of our data:" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " A B C D\n", - "count 6.000000 6.000000 6.000000 6.000000\n", - "mean -0.439675 -0.442039 -0.329139 0.012365\n", - "std 1.456953 0.691383 0.918213 1.306626\n", - "min -2.312278 -1.430888 -1.414519 -1.663592\n", - "25% -1.471733 -0.882513 -0.913870 -0.784893\n", - "50% -0.350560 -0.384032 -0.526971 -0.170488\n", - "75% 0.617044 0.062510 0.332621 0.861654\n", - "max 1.281230 0.384033 0.917312 1.862749\n" - ] - } - ], - "source": [ - "print(d.describe())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Accessing columns and rows of a dataframe is similar to lists and arrays - for columns we index as normal:" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0 -1.304458\n", - "1 -2.312278\n", - "2 -1.527491\n", - "3 0.621613\n", - "4 0.603338\n", - "5 1.281230\n", - "Name: A, dtype: float64\n" - ] - } - ], - "source": [ - "print(d['A'])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For rows, we need to use the loc method:" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "A -1.304458\n", - "B 0.128916\n", - "C 0.917312\n", - "D -0.830153\n", - "Name: 0, dtype: float64\n" - ] - } - ], - "source": [ - "print(d.loc[0])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And finally, to get induvidual values, we can use a double-index:" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "-1.3044583932951868" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "d['A'][0]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, we can filter our data using logical expressions, to access the row in our dataframe e where column A is equal to 3 we can use: " - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " A B C\n", - "2 3 hello 2017-04-01\n" - ] - } - ], - "source": [ - "print(e[e['A'] == 3])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Worked Example" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "We're going to take a closer look at the random.randn function to see how this data is distributed:" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " 0\n", - "count 100000.000000\n", - "mean -0.002194\n", - "std 1.000691\n", - "min -4.194139\n", - "25% -0.673841\n", - "50% 0.000094\n", - "75% 0.671483\n", - "max 4.440165\n" - ] - } - ], - "source": [ - "import numpy as np\n", - "import pandas as pd\n", - "\n", - "myData = pd.DataFrame(np.random.randn(100000))\n", - "\n", - "print(myData.describe())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "So our random data has a mean of about 0 and a standard deviation of around 1. This seems to be a standard normal distribution, and in fact that's true - the \"n\" of \"randn\" stands for normal. We can illustrate this using a graph:" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "mySortedData = myData.sort_values(0) #sorts the data in ascending order\n", - "x = np.linspace(-10, 10, 100000) #setting up a dummy array\n", - "\n", - "plt.plot(mySortedData,x)\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we can see the cumulative distribution function of the normal distribution!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Mini Project" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Below we have a dataframe of marks in a class - can you find out:\n", - "\n", - "* The average mark for English?\n", - "* Each student's average mark? (DON'T do this manually!!!)\n", - "* The subject which, on average, students scored the least marks in?\n", - "* The subject which each induvidual student did worst in.\n", - "* The student who got the most marks in the class overall" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import pandas as pd\n", - "\n", - "subjects = [\"Maths\",\"English\",\"Science\",\"Geography\",\"History\",\"Languages\"]\n", - "marks = pd.DataFrame({\"Alice\": [85, 86, 98, 94, 2, 39],\"Billy\": [55, 26, 69, 39, 47, 15],\"Cameron\": [80, 5, 28, 28, 44, 37],\"David\": [ 5, 22, 95, 71, 62, 6],\"Ellie\": [75, 93, 66, 18, 87, 60],\"Faye\": [72, 0, 63, 51, 65, 83],\"Garry\": [67, 92, 62, 35, 0, 79],\"Harriet\": [51, 17, 87, 31, 91, 99],\"Izzy\": [63, 37, 58, 26, 39, 51],\"James\": [17, 7, 88, 27, 6, 16],\"Katie\": [15, 77, 12, 54, 81, 0],\"Liam\": [25, 35, 80, 71, 71, 9],\"Mason\": [70, 78, 4, 19, 61, 77],\"Noah\": [78, 96, 86, 42, 73, 51],\"Olivia\": [75, 81, 23, 19, 76, 3],\"Patrick\": [43, 50, 87, 94, 33, 65],\"Quinn\": [72, 1, 80, 96, 76, 56],\"Ross\": [ 3, 25, 30, 49, 84, 7],\"Sam\": [67, 29, 91, 64, 11, 43],\"Terri\": [63, 36, 70, 73, 13, 25],\"Umar\": [70, 30, 47, 71, 25, 57],\"Veronica\": [88, 34, 29, 92, 82, 62],\"Will\": [89, 11, 14, 56, 78, 63]}, index=subjects)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.6" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/[BASICS] Setting Up Python/HiPy.pub b/[BASICS] Setting Up Python/HiPy.pub deleted file mode 100644 index 2aff363..0000000 Binary files a/[BASICS] Setting Up Python/HiPy.pub and /dev/null differ diff --git a/[BASICS] Setting Up Python/Setting Up Python Intro Document.pdf b/[BASICS] Setting Up Python/Setting Up Python Intro Document.pdf deleted file mode 100644 index 2c66c0c..0000000 Binary files a/[BASICS] Setting Up Python/Setting Up Python Intro Document.pdf and /dev/null differ diff --git a/[STATISTICS] ANOVA (Analysis Of Variance)/.ipynb_checkpoints/ANOVA (Analysis Of Variance)-checkpoint.ipynb b/[STATISTICS] ANOVA (Analysis Of Variance)/.ipynb_checkpoints/ANOVA (Analysis Of Variance)-checkpoint.ipynb deleted file mode 100644 index ecd0915..0000000 --- a/[STATISTICS] ANOVA (Analysis Of Variance)/.ipynb_checkpoints/ANOVA (Analysis Of Variance)-checkpoint.ipynb +++ /dev/null @@ -1,368 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![title](header.png)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "ANOVA (Analysis Of Variance) lets us test to see if a number of samples have the same mean. It's similar to the independent 2-sample t-test, but doesn't restrict us to just 2 samples. We will look at one-way and two-way ANOVA, and by the end of this guide you should be confident in using these statistical methods in your own work." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## One Way ANOVA" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "One way ANOVA can be used when we have data categorised by 1 variable - for example, take the following dataframe of the force applied to a drivers head during a crash in 3 different sizes of cars:" - ] - }, - { - "cell_type": "code", - "execution_count": 60, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Compact Large Medium\n", - "0 543 600 566\n", - "1 555 530 520\n", - "2 502 498 580\n", - "3 534 460 498\n", - "4 611 478 511\n", - "5 622 560 560\n" - ] - } - ], - "source": [ - "import numpy as np\n", - "import pandas as pd\n", - "\n", - "cars = pd.DataFrame({\"Compact\": [543, 555, 502, 534, 611, 622], \"Medium\": [566,520,580,498,511,560], \"Large\": [600,530,498,460,478,560]})\n", - "\n", - "print(cars)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "A simple preliminary technique is to plot the boxplots of the different sets using matplotlib:" - ] - }, - { - "cell_type": "code", - "execution_count": 61, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n/wEs38uzkwSEuAAAAABJRU5ErkJggg==\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "plt.boxplot([cars[\"Compact\"], cars[\"Medium\"], cars[\"Large\"]])\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It certainly looks like these is some kind of downward trend as the car gets larger - but we need a way of statistically testing if the means are different. ANOVA lets us do this, and works on the assumption that every data point is picked independently from normal distributions with the same variance. Of course - each group can have a different mean (otherwise our data would all be the same), but the variance has to be equal. In ANOVA, the null hypothesis is that all the means are equal, and the alternative hypothesis is they are not." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Scipy has a really nice and easy way to do this: the f_oneway() function:" - ] - }, - { - "cell_type": "code", - "execution_count": 62, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "F_onewayResult(statistic=1.1973440463010667, pvalue=0.3292756379801583)\n" - ] - } - ], - "source": [ - "import scipy.stats as stats\n", - "\n", - "print(stats.f_oneway(cars[\"Compact\"], cars[\"Medium\"], cars[\"Large\"]))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we can see a pvalue of 0.32 gives us no evidence the means are different. If we want more detailed output, we can use the statsmodels library to get more control over what's happening. For this we need to edit our dataframe a little. The melt method for pandas lets us do this really easily:" - ] - }, - { - "cell_type": "code", - "execution_count": 63, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Type Force\n", - "0 Compact 543\n", - "1 Compact 555\n", - "2 Compact 502\n", - "3 Compact 534\n", - "4 Compact 611\n", - "5 Compact 622\n", - "6 Large 600\n", - "7 Large 530\n", - "8 Large 498\n", - "9 Large 460\n", - "10 Large 478\n", - "11 Large 560\n", - "12 Medium 566\n", - "13 Medium 520\n", - "14 Medium 580\n", - "15 Medium 498\n", - "16 Medium 511\n", - "17 Medium 560\n" - ] - } - ], - "source": [ - "cars2 = pd.melt(cars, var_name=\"Type\", value_name=\"Force\")\n", - "print(cars2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can use the statsmodels libary to build a model and then perform the analysis:" - ] - }, - { - "cell_type": "code", - "execution_count": 92, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " sum_sq df F PR(>F)\n", - "C(Type) 4854.777778 2.0 1.197344 0.329276\n", - "Residual 30409.666667 15.0 NaN NaN\n" - ] - } - ], - "source": [ - "import statsmodels.api as sm\n", - "from statsmodels.formula.api import ols\n", - "\n", - "#Fits the data to a model using the formula \"Force ~ C(Type)\" - since Type is categorical we need the C()\n", - "model = ols('Force ~ C(Type)', data=cars2).fit() \n", - " \n", - "anova_table = sm.stats.anova_lm(model, typ=2) #Performs Analysis on this model\n", - "print(anova_table)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we can see the test statistic (1.197) and our p-value again (0.329) as well as the sum of squares data. This method doesn't seem useful now, but will be useful when we look at the next section." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Two Way ANOVA" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Two way ANOVA is similar to one way ANOVA in that we're testing data split catagorically for equal means. However this time, our data is sorted into two different types of categories, and what we're testing for is slightly different. The assumptions here are the same as one-way ANOVA, but the groups also must be the same size. We are also testing three null hypothesis at once:\n", - "\n", - "* The Population Means of the first factor are equal (One-way ANOVA on the first type of category)\n", - "* The Population Means of the second factor are equal (One-way ANOVA on the second type of category)\n", - "* There is no interaction between the two factors." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we are looking at the length of odontoblasts (cells responsible for tooth growth) in 60 guinea pigs. As this dataset is too large to copy out, we're going to import it. You can download the datafile from the same folder this notebook is in [here](https://www.google.co.uk)" - ] - }, - { - "cell_type": "code", - "execution_count": 101, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " len supp dose\n", - "0 4.2 VC 0.5\n", - "1 11.5 VC 0.5\n", - "2 7.3 VC 0.5\n", - "3 5.8 VC 0.5\n", - "4 6.4 VC 0.5\n" - ] - } - ], - "source": [ - "teeth = pd.read_csv(\"ToothGrowth.csv\")\n", - "print(teeth.head())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The data is split into three columns: our dependent variable - the length of odontoblasts, the form of the suppliment given (OJ is orange juice, VC is ascorbic acid), and the dose of vitamin C they were given. Statsmodels lets us perform a two-way ANOVA test using a similar method to above:" - ] - }, - { - "cell_type": "code", - "execution_count": 99, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " sum_sq df F PR(>F)\n", - "C(supp) 205.350000 1.0 15.571979 2.311828e-04\n", - "C(dose) 2426.434333 2.0 91.999965 4.046291e-18\n", - "C(supp):C(dose) 108.319000 2.0 4.106991 2.186027e-02\n", - "Residual 712.106000 54.0 NaN NaN\n" - ] - } - ], - "source": [ - "import statsmodels.api as sm\n", - "from statsmodels.formula.api import ols\n", - " \n", - "model = ols('len ~ C(supp) + C(dose) + C(supp)*C(dose)', data=teeth).fit() #Formula for Two-way ANOVA is C(1) + C(2) + C(1)*C(2)\n", - " \n", - "anova_table = sm.stats.anova_lm(model, typ=2) #Performs Analysis on this model\n", - "print(anova_table)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The first line gives us a p-value of 2.3e-04, which gives us strong evidence that the means are not equal when categorised by suppliment (i.e, orange juice gives different results than ascorbic acid).\n", - "\n", - "The second line gives us a p-value of 4.04e-18, which again gives us strong evidence that the means are not equal when categorised by dose (i.e, different doses give us different growths).\n", - "\n", - "The third line give us a p-value of 0.02186, which gives us evidence that the two categorical factors are related in some way." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Mini Project" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Here we have some data detailing the anger scores categorised by gender, and whether or not they are athletes. You can download the datafile from the same folder this notebook is in [here](https://www.google.co.uk). The \"AngerOut\" score is a measurement of verbally or phyiscally expressing anger." - ] - }, - { - "cell_type": "code", - "execution_count": 107, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Gender Sports AngerOut\n", - "0 female athlete 18\n", - "1 female athlete 14\n", - "2 female athlete 13\n", - "3 female athlete 17\n", - "4 male athlete 16\n" - ] - } - ], - "source": [ - "angry = pd.read_csv(\"angry_moods.csv\")\n", - "print(angry.head())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Can you perform analysis on the data set and conclude if:\n", - "\n", - "* Men and Women express their anger to a similar degree.\n", - "* Athletes and Non-athletes express their anger to a similar degree.\n", - "* There is any relationship between whether or not someone is an athelete, their gender, and if they express their anger phyisically or verbally." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.2" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/[STATISTICS] Hypothesis Testing In Python/.ipynb_checkpoints/Hypothesis Testing In Python-checkpoint.ipynb b/[STATISTICS] Hypothesis Testing In Python/.ipynb_checkpoints/Hypothesis Testing In Python-checkpoint.ipynb deleted file mode 100644 index f88bb15..0000000 --- a/[STATISTICS] Hypothesis Testing In Python/.ipynb_checkpoints/Hypothesis Testing In Python-checkpoint.ipynb +++ /dev/null @@ -1,388 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![title](header.png)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Hypothesis testing is the most basic form of analyical statistics. It works by us giving a null hypothesis, say, the mean of a population being equal to 50, then using samples from the same population we can test whether our null hypothesis is true or not. Hypothesis testing is easy to do with Python using the scipy library - and the statsmodels library can give us some additional functionality when needed. By the end of this guide you should be comfortable using Python to perform simple hypothesis test and be able to apply it to real world problems." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Student's T-Test" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Student's T-Test can tell us if two means are equal, or if a mean is equal to a particular value. Below we have the data for IQ scores for 50 people, and we want to test, using the sample, if the mean of the general population is equal to 100." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "scores = [117,137,105,120,44,94,89,61,92,123,130,119,79,119,95,95,108,92,110,121,85,65,84,100,83,74,80,127,106,88,145,86,123,107,91,77,72,138,92,50,102,96,109,97,141,82,94,115,101,91]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For a preliminary look at our data, we can quickly graph it as a histogram using matplotlib:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAD8CAYAAABn919SAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAADD5JREFUeJzt3V+MpfVdx/H3R9b+WWwKuCO2LOMQQzCVqCUT05akMYBK\nXcL2wottxFBtMle22DRpFhttvMPYaLnwTzaUQiyBC0RLoFaQ2jQmiu4CbRcWBMsKS6G7TeN/IxC/\nXsxpnA477J7zPHtm57vvVzKZc55zZp7fd9l98+Q5/1JVSJK2vu/b7AVIksZh0CWpCYMuSU0YdElq\nwqBLUhMGXZKaMOiS1IRBl6QmDLokNbFtnjvbsWNHLS0tzXOXkrTlHThw4NtVtXCi+8016EtLS+zf\nv3+eu5SkLS/JP5/M/TzlIklNGHRJasKgS1ITBl2SmjDoktSEQZekJgy6JDVh0CWpCYMuSU3M9ZWi\n0oks7b1/U/Z7+KZdm7JfaUweoUtSEwZdkpow6JLUhEGXpCYMuiQ1YdAlqQmDLklNGHRJasKgS1IT\nBl2SmjDoktSEQZekJgy6JDVh0CWpiRMGPcmtSY4mObhm23lJHkzy9OT7uad2mZKkEzmZI/TbgKvX\nbdsLPFRVFwMPTa5LkjbRCYNeVV8BvrNu827g9snl24H3j7wuSdKUZj2Hfn5VvTi5/BJw/kjrkSTN\naPCDolVVQG10e5KVJPuT7D927NjQ3UmSNjBr0L+V5G0Ak+9HN7pjVe2rquWqWl5YWJhxd5KkE5k1\n6PcC108uXw98fpzlSJJmdTJPW7wT+FvgkiRHknwIuAn42SRPA1dNrkuSNtG2E92hqj6wwU1XjrwW\nSdIAvlJUkpow6JLUhEGXpCYMuiQ1YdAlqQmDLklNGHRJasKgS1ITBl2SmjDoktSEQZekJgy6JDVh\n0CWpCYMuSU0YdElqwqBLUhMGXZKaMOiS1IRBl6QmDLokNWHQJakJgy5JTRh0SWrCoEtSEwZdkpow\n6JLUhEGXpCYMuiQ1YdAlqYlBQU/y0SSPJzmY5M4kbxprYZKk6cwc9CQXAB8BlqvqUuAsYM9YC5Mk\nTWfoKZdtwJuTbAO2A98cviRJ0iy2zfqDVfVCkk8BzwH/DTxQVQ+sv1+SFWAFYHFxcdbdSRrZ0t77\nN23fh2/atWn77mzIKZdzgd3ARcDbgbOTXLf+flW1r6qWq2p5YWFh9pVKkl7XkFMuVwHPVtWxqnoF\nuAd4zzjLkiRNa0jQnwPelWR7kgBXAofGWZYkaVozB72qHgbuBh4Bvj75XftGWpckaUozPygKUFWf\nBD450lokSQP4SlFJasKgS1ITBl2SmjDoktSEQZekJgy6JDVh0CWpCYMuSU0YdElqwqBLUhMGXZKa\nMOiS1IRBl6QmBr3botSFH8emDjxCl6QmDLokNWHQJakJgy5JTRh0SWrCoEtSEwZdkpow6JLUhEGX\npCYMuiQ1YdAlqQmDLklNGHRJasKgS1ITg4Ke5Jwkdyd5MsmhJO8ea2GSpOkMfT/0m4EvVtUvJnkD\nsH2ENUmSZjBz0JO8FXgv8EGAqnoZeHmcZUmSpjXklMtFwDHgs0keTXJLkrNHWpckaUpDTrlsAy4D\nPlxVDye5GdgL/ObaOyVZAVYAFhcXB+xO87KZH8d2JvLPW2MZcoR+BDhSVQ9Prt/NauC/R1Xtq6rl\nqlpeWFgYsDtJ0uuZOehV9RLwfJJLJpuuBJ4YZVWSpKkNfZbLh4E7Js9w+QbwK8OXJEmaxaCgV9Vj\nwPJIa5EkDeArRSWpCYMuSU0YdElqwqBLUhMGXZKaMOiS1IRBl6QmDLokNWHQJakJgy5JTRh0SWrC\noEtSEwZdkpow6JLUhEGXpCYMuiQ1YdAlqQmDLklNGHRJasKgS1ITBl2SmjDoktSEQZekJgy6JDVh\n0CWpCYMuSU0YdElqwqBLUhMGXZKaGBz0JGcleTTJfWMsSJI0mzGO0G8ADo3weyRJAwwKepKdwC7g\nlnGWI0ma1baBP/9p4OPAWza6Q5IVYAVgcXFx4O4kaXZLe+/ftH0fvmnXKd/HzEfoSa4BjlbVgde7\nX1Xtq6rlqlpeWFiYdXeSpBMYcsrlcuDaJIeBu4ArknxulFVJkqY2c9Cr6saq2llVS8Ae4EtVdd1o\nK5MkTcXnoUtSE0MfFAWgqr4MfHmM3yVJmo1H6JLUhEGXpCYMuiQ1YdAlqQmDLklNGHRJasKgS1IT\nBl2SmjDoktSEQZekJgy6JDVh0CWpCYMuSU2M8m6LOjU28+OyJG09HqFLUhMGXZKaMOiS1IRBl6Qm\nDLokNWHQJakJgy5JTRh0SWrCoEtSEwZdkpow6JLUhEGXpCYMuiQ1YdAlqYmZg57kwiR/neSJJI8n\nuWHMhUmSpjPk/dBfBT5WVY8keQtwIMmDVfXESGuTJE1h5iP0qnqxqh6ZXP534BBwwVgLkyRNZ5Rz\n6EmWgHcCD4/x+yRJ0xv8EXRJfgD4U+DXq+rfjnP7CrACsLi4OPN+NvPj2A7ftGvT9i115McrnhqD\njtCTfD+rMb+jqu453n2qal9VLVfV8sLCwpDdSZJex5BnuQT4DHCoqn5vvCVJkmYx5Aj9cuCXgSuS\nPDb5+oWR1iVJmtLM59Cr6m+AjLgWSdIAvlJUkpow6JLUhEGXpCYMuiQ1YdAlqQmDLklNGHRJasKg\nS1ITBl2SmjDoktSEQZekJgy6JDVh0CWpCYMuSU0M/gi6M4EflyVpK/AIXZKaMOiS1IRBl6QmDLok\nNWHQJakJgy5JTRh0SWrCoEtSEwZdkpow6JLUhEGXpCYMuiQ1YdAlqQmDLklNDAp6kquTPJXkmSR7\nx1qUJGl6Mwc9yVnAHwDvA94BfCDJO8ZamCRpOkOO0H8aeKaqvlFVLwN3AbvHWZYkaVpDgn4B8Pya\n60cm2yRJm+CUfwRdkhVgZXL1P5I8Nbm8A/j2qd7/aeRMmxfOvJmdt7dB8+Z3Bu37R07mTkOC/gJw\n4ZrrOyfbvkdV7QP2rd+eZH9VLQ/Y/5Zyps0LZ97MztvbVph3yCmXfwAuTnJRkjcAe4B7x1mWJGla\nMx+hV9WrSX4N+EvgLODWqnp8tJVJkqYy6Bx6VX0B+MKMP/6a0zDNnWnzwpk3s/P2dtrPm6ra7DVI\nkkbgS/8lqYm5BT3JWUkeTXLf5Pp5SR5M8vTk+7nzWss8JDknyd1JnkxyKMm7O8+c5KNJHk9yMMmd\nSd7Uad4ktyY5muTgmm0bzpfkxslbYjyV5Oc3Z9XDbDDz707+Tn8tyZ8lOWfNbVt65uPNu+a2jyWp\nJDvWbDvt5p3nEfoNwKE11/cCD1XVxcBDk+ud3Ax8sap+DPhJVmdvOXOSC4CPAMtVdSmrD5Lvode8\ntwFXr9t23Pkmb4GxB/jxyc/84eStMraa23jtzA8Cl1bVTwD/CNwIbWa+jdfOS5ILgZ8Dnluz7bSc\ndy5BT7IT2AXcsmbzbuD2yeXbgffPYy3zkOStwHuBzwBU1ctV9S80npnVB9jfnGQbsB34Jo3mraqv\nAN9Zt3mj+XYDd1XV/1TVs8AzrL5VxpZyvJmr6oGqenVy9e9Yff0JNJh5g//GAL8PfBxY+4DjaTnv\nvI7QP83qH8j/rtl2flW9OLn8EnD+nNYyDxcBx4DPTk4z3ZLkbJrOXFUvAJ9i9QjmReBfq+oBms67\nxkbznSlvi/GrwF9MLrecOclu4IWq+uq6m07LeU950JNcAxytqgMb3adWn2rT6ek224DLgD+qqncC\n/8m60w2dZp6cO97N6v/I3g6cneS6tffpNO/xdJ9vvSSfAF4F7tjstZwqSbYDvwH81mav5WTN4wj9\ncuDaJIdZfUfGK5J8DvhWkrcBTL4fncNa5uUIcKSqHp5cv5vVwHed+Srg2ao6VlWvAPcA76HvvN+1\n0Xwn9bYYW1WSDwLXAL9U//+8544z/yirBylfnfRrJ/BIkh/mNJ33lAe9qm6sqp1VtcTqgwhfqqrr\nWH2bgOsnd7se+PypXsu8VNVLwPNJLplsuhJ4gr4zPwe8K8n2JGF13kP0nfe7NprvXmBPkjcmuQi4\nGPj7TVjf6JJczerp02ur6r/W3NRu5qr6elX9UFUtTfp1BLhs8u/79Jy3qub2BfwMcN/k8g+y+syA\np4G/As6b51rmMOtPAfuBrwF/DpzbeWbgt4EngYPAnwBv7DQvcCerjw+8wuo/7A+93nzAJ4B/Ap4C\n3rfZ6x9x5mdYPXf82OTrj7vMfLx5191+GNhxOs/rK0UlqQlfKSpJTRh0SWrCoEtSEwZdkpow6JLU\nhEGXpCYMuiQ1YdAlqYn/AwzQkNgsKm+5AAAAAElFTkSuQmCC\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "plt.hist(scores)\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The student t-test assumes our data is normally distributed - meaning the data has a bell shape to it. While we can see our data above isn't perfect, it's good enough to continue.\n", - "\n", - "We want to test if the mean IQ of the population is 100 using this sample. The function we want is ttest_1samp() in the scipy.stats module. Let's run this and see what we get:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Ttest_1sampResult(statistic=-0.30763272152834936, pvalue=0.75966563634430628)\n" - ] - } - ], - "source": [ - "import scipy.stats as stats #can also be written as \"from scipy import stats\"\n", - "\n", - "print(stats.ttest_1samp(scores,100))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What does this output mean? The statistic is a helpful number to have because it's the number we compare to the distribution (in this case, the t-49 distribution) to make our conclusions. The pvalue is what we're interested in. It's the probability that given the null hypothesis (the mean being 100), our sample gives us the result it does. How do we convert this to a definitive yes/no result? We need to use significance levels. Significance levels are thresholds at which we reject or accept our null hypothesis depending on the p-value. If the p-value is above our significance level, we cannot reject our null hypothesis - but if it is lower, we can. Typically we use a significance value of 5%, but larger or smaller significance levels can be used. Remember - the smaller the significane level, the stronger evidence we have to reject our null hypothesis if the p-value is lower than it.\n", - "\n", - "In our case, a p-value of 75.9% is well above 5%, so there is no reason to reject our null hypothesis of the population mean being equal to 100.\n", - "\n", - "To show you what happens when the null hypothesis is false, let's look at what happens when we test for the null hypothesis being equal to 150:" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Ttest_1sampResult(statistic=-16.003179738280803, pvalue=4.2848532726844928e-21)\n" - ] - } - ], - "source": [ - "print(stats.ttest_1samp(scores,150))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Our p-value is now 4.28 e-21 - that's very, very small. In other words, there is very strong evidence (p-value < 1%) that the population mean for IQ is not 150, as we'd expect." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": true - }, - "source": [ - "We've looked at a one-sample t-test, testing if one sample is equal to a mean we choose ourselves - but what if we want to test if two samples are equal? For this we need to use an independent 2-sample t-test. This test assumes the variances of the two sets are roughly equal - we can test this later. Below we have the same data, but split into genders:" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[117, 137, 105, 120, 44, 94, 89, 61, 92, 123, 130, 119, 79, 119, 95, 95, 108, 92, 110, 121, 85, 65]\n", - "[84, 100, 83, 74, 80, 127, 106, 88, 145, 86, 123, 107, 91, 77, 72, 138, 92, 50, 102, 96, 109, 97, 141, 82, 94, 115, 101, 91]\n" - ] - } - ], - "source": [ - "scores = [117,137,105,120,44,94,89,61,92,123,130,119,79,119,95,95,108,92,110,121,85,65,84,100,83,74,80,127,106,88,145,86,123,107,91,77,72,138,92,50,102,96,109,97,141,82,94,115,101,91]\n", - "men = scores[:22] #The data was sorted so the first 21 entries were men.\n", - "women = scores[22:] #So from the 22nd onwards we have the women.\n", - "print(men)\n", - "print(women)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Testing if the means are equal is easy, using the ttest_ind() function. Here the null hypothesis is that the two means are equal." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Ttest_indResult(statistic=0.27009541129591547, pvalue=0.78824475119470483)\n" - ] - } - ], - "source": [ - "print(stats.ttest_ind(men,women))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Again, we have a p-value of 79%, meaning there is no evidence to reject the null hypothesis. Therefore from this test we can conclude that men and women have the same average IQ." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There's a special case of two sampled t-test where the data is paired - for example, if we give 25 people a drug and measure their heart rate before and 15mins after taking the drug, we have 25 data points for each sample. For each data point in the control set we have a corresponding data point in the other set from the same person, so our data is paired. We also don't need for both sets of data to be normally distributed - it's enough for just the difference to be. If these condition are met, we can use a more powerful version of the independent 2 sample t-test; the 2 sample paired t-test. Below we have the data for the experiment above:" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "control = [70, 80, 86, 92, 84, 69, 73, 101, 78, 72, 74, 83, 80, 73, 84, 85, 80, 85, 74, 84, 79, 83, 86, 76, 77]\n", - "fifteen = [89, 99, 105, 111, 103, 87, 92, 119, 96, 91, 93, 102, 98, 92, 103, 104, 98, 104, 92, 103, 97, 102, 105, 95, 96]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this situation we use the ttest_rel() function - the null hypothesis here is that the means are equal:" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Ttest_relResult(statistic=-204.25194526088882, pvalue=2.1036620058407739e-40)" - ] - }, - "execution_count": 37, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "stats.ttest_rel(control,fifteen)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Our p-value is 2.1 e-40, which strongly suggests that the means are not equal.\n", - "\n", - "The paired t-test is more powerful than the independent t-test, meaning that it will pick up on smaller differences between the two means." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Testing For Equal Variance" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If we have two samples we want to test for equal variance, either for a direct test or to check we are okay to use one of the tests above, we have a couple of options:\n", - "\n", - "* F-test (extremely dependent on normality, which isn't very helpful for us)\n", - "* Bartlett's Test\n", - "* Levene's Test (better than Barlett's test for data which is not normally distributed)\n", - "\n", - "Scipy has functions for Bartlett's Test and Levene's test, which are bartlett() and levene respectively. For both of these, the null hypothesis is that the variances are equal. Let's test to see if the variances are equal for our IQs split by gender is the same:" - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "BartlettResult(statistic=0.11379496878318175, pvalue=0.73586430378344914)\n", - "LeveneResult(statistic=0.37710466803928877, pvalue=0.54205660176957238)\n" - ] - } - ], - "source": [ - "print(stats.bartlett(men,women))\n", - "print(stats.levene(men,women))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Both tests show us that there is no reason to assume the variances aren't equal. The tests we did earlier are valid!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Testing For Normality" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Some of our tests require that our data is normally distributed. For this we can use D’Agostino and Pearson's test by using the normaltest() function. Let's test if our IQs were normally distributed:" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "NormaltestResult(statistic=0.10212051194763901, pvalue=0.95022141229082702)\n" - ] - } - ], - "source": [ - "print(stats.normaltest(scores))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Looks like they are! Most tests are robust against non-normality, meaning that even if the data isn't normally distributed, the test will still work - however, it's always worth testing to see how worried we should be - if our p-value came back below 0.01, it might be a good idea to use a different, non-parametric test." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Mini Project" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Below we have two runners, Angela and Bill, and 50 training times for an upcoming race. Using statistical tests, test to see if;\n", - "\n", - "* The two means are the same.\n", - "* The two variances are the same.\n", - "* The data is normally distributed." - ] - }, - { - "cell_type": "code", - "execution_count": 58, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "angela = [141, 151, 151, 154, 150, 143, 153, 149, 156, 144, 158, 147, 145, 149, 159, 154, 150, 154, 145, 151, 160, 151, 149, 158, 139, 165, 149, 157, 153, 154, 144, 148, 147, 153, 144, 151, 143, 153, 151, 142, 144, 147, 142, 149, 147, 154, 150, 138, 150, 148]\n", - "bill = [103, 109, 93, 95, 107, 96, 102, 99, 105, 101, 99, 107, 102, 95, 98, 112, 95, 110, 103, 107, 100, 95, 92, 101, 103, 95, 97, 102, 99, 108, 98, 100, 100, 97, 101, 92, 101, 108, 102, 93, 101, 99, 105, 100, 101, 100, 92, 92, 92, 90]" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.2" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/__pycache__/fizzbuzz.cpython-35.pyc b/__pycache__/fizzbuzz.cpython-35.pyc deleted file mode 100644 index 6476114..0000000 Binary files a/__pycache__/fizzbuzz.cpython-35.pyc and /dev/null differ diff --git a/docs/CNAME b/docs/CNAME deleted file mode 100644 index e8de1ff..0000000 --- a/docs/CNAME +++ /dev/null @@ -1 +0,0 @@ -www.hipy.uk \ No newline at end of file diff --git a/docs/contact.html b/docs/contact.html deleted file mode 100644 index 9d29dea..0000000 --- a/docs/contact.html +++ /dev/null @@ -1,15 +0,0 @@ - -
-
-

Contact

-

Got a question? Complete the form below. We'll get back to you.


-
-
-
-
-
-
- -

-
-
\ No newline at end of file diff --git a/docs/css/basic.css b/docs/css/basic.css deleted file mode 100644 index 6a77508..0000000 --- a/docs/css/basic.css +++ /dev/null @@ -1,421 +0,0 @@ -*:focus { - outline: none; } - -.navbar { - font-size: 1.2em; } - -.navbar-brand { - font-size: 1.2em; } - -.title { - white-space: normal; } - -.sponsors img, .support img { - margin-right: 5px; - margin-bottom: 5px; } - -.sponsors img { - max-width: 250px; } - -.support img { - max-width: 150px; } - -hr.style-two { - border: 0; - height: 3px; - background-image: linear-gradient(to right, transparent, #ffe9d3, transparent); - margin-left: 25%; - margin-right: 25%; - margin-top: 75px; - margin-bottom: 75px; } - -body { - font-size: 18px; } - -.full-height { - min-height: 100vh; } - -.headline { - padding-top: 5px; } - -h1.big-title { - font-size: 4em; - margin-top: 10px; } - -font.pink { - color: #ffe9d3; } - -.vertical-center { - min-height: 100%; - /* Fallback for browsers do NOT support vh unit */ - min-height: 100vh; - /* These two lines are counted as one :-) */ - display: flex; - align-items: center; } - -.row { - width: 100%; - margin: 0; } - -span.page-info { - font-size: 1.3em; - margin-top: 20px; - margin-bottom: 20px; - display: block; } - -.btn-info { - background-color: transparent; - font-size: 1.3em; - border-radius: 0px; - border: 2px grey solid; - color: grey; } - -.google-maps { - position: relative; - padding-bottom: 75%; - height: 0; - overflow: hidden; } - -.google-maps iframe { - position: absolute; - top: 0; - left: 0; - width: 100% !important; - min-height: 500px; } - -.event-box { - display: table; - padding-top: 100px; } - -.event-box-line { - display: table-cell; - vertical-align: middle; } - -.event-info { - float: right; - margin: 10px; } - -.event-info h3, p { - margin-top: 0px; - margin-bottom: 10px; } - -.left { - float: left; - margin: 10px; - line-height: 100%; } - -.wrapper { - display: inline-block; - white-space: nowrap; } - -.block { - white-space: normal; - vertical-align: middle; - float: none; } - -.image { - max-height: 100%; - max-width: 50%; } - -#main { - width: 100%; - background-color: #ff873a; } - -#support h1.big-title { - font-size: 2em; } - -#why { - width: auto; - background-repeat: no-repeat; - background-size: contain; } - -#how { - background-image: url("../img/what.jpg"); - width: auto; - background-repeat: no-repeat; } - -#footer { - background-image: url("../img/footer-bg.jpg"); - width: auto; - background-repeat: no-repeat; - color: #333; - padding: 100px; } - -#footer img { - max-width: 200px; } - -#footer.vertical-center { - min-height: 0; - height: auto; } - -.parallax { - /* Set a specific height */ - /* Create the parallax scrolling effect */ - background-attachment: fixed; - background-size: cover; } - -.left { - line-height: 0; - margin: 0; } - -.slider { - margin-top: 20px; } - -.btn-primary { - font-family: 'Heebo', sans-serif; - color: #f4f4f4; - background-color: #333; - margin-top: 20px; - margin-bottom: 20px; - border-color: #ffe9d3; - border-radius: 5px; - padding: 10px; - -webkit-animation: btnWiggle 5s infinite; - -moz-animation: btnWiggle 5s infinite; - -o-animation: btnWiggle 5s infinite; - animation: btnWiggle 5s infinite; } - -.programme-btn:focus { - outline-color: blue !important; } - -.btn-primary:hover { - background-color: #da6314; - border-color: #da6314; } - -.tg { - border-collapse: collapse; - border-spacing: 10px; - width: 100%; } - -.tg td { - font-family: 'Heebo', sans-serif; - font-size: 1em; - padding: 20px 20px; - border-style: solid; - border-width: 3px; - overflow: hidden; - word-break: normal; - border-left: none; - border-right: none; } - -.tg th { - font-family: 'Heebo', sans-serif; - font-size: 1em; - font-weight: bold; - padding: 20px 20px; - border-style: solid; - border-width: 1px; - overflow: hidden; - word-break: normal; - border-left: none; - border-right: none; } - -.tg .tg-yw4l { - vertical-align: top; } - -tr.head { - background-color: #333; - color: #fff; } - -tr.write { - color: #ffe9d3; } - -table#sunday, table#saturday { - display: none; } - -#fixedbtn-up, #fixedbtn-reg, #fixedbtn-twitter, #fixedbtn-facebook, #fixedbtn-instagram, #fixedbtn-slack, #fixedbtn-github, #fixedbtn-teams .nav-bottom { - position: fixed; - bottom: 20px; - right: 20px; - background-color: #333; - color: #f4f4f4; - font-size: 0.9em; - padding: 10px 10px; - width: 50px; - height: 50px; - border-radius: 50px; - text-align: center; - padding: 5px; - margin: 0px; - display: none; } - -#fixedbtn-twitter { - right: 20px; - bottom: 140px; - display: block; } - -#fixedbtn-instagram { - right: 20px; - top: 285px; - display: block; } - -#fixedbtn-teams { - right: 20px; - top: 350px; - display: block; } - -#fixedbtn-github { - right: 20px; - bottom: 80px; - display: block; } - -#fixedbtn-twitter svg, #fixedbtn-facebook, #fixedbtn-slack svg, #fixedbtn-github svg, #fixedbtn-instagram svg { - padding-top: 5px; - margin-top: 2px; } - -.inner-fixedbtn-up, .inner-fixedbtn-reg, .inner-fixedbtn-twitter, .inner-fixedbtn-facebook, .inner-fixedbtn-instagram { - line-height: 50px; } - -#fixedbtn-reg { - right: 80px; - width: 200px; - border-radius: 5px; - font-size: 1.2em; - line-height: 50px; - margin: 0px; - padding: 0px; - display: none; } - -#fixedbtn-offer { - width: 250px; - height: 250px; - border-radius: 250px; - display: table; - transform: rotate(20deg); - background-color: #ffe9d3; - color: #fff; - font-size: 1.0em; - padding: 10px 10px; - text-align: center; - padding: 5px; - margin: 0px; - margin-top: 2px; - line-height: 1.2em; } - -#fixedbtn-offer font.small { - font-size: 0.6em; } - -#fixedbtn-offer font.large { - font-size: 3em; - line-height: 1.0em; } - -.inner-fixedbtn-offer { - display: table-cell; - vertical-align: middle; } - -.nav-bottom { - bottom: 0px; - right: 0px; - left: 0px; - height: 55px; - width: 100%; - border-radius: 0px; - padding: 0px; - margin: 0px; - display: none; } - -.nav-bottom a { - text-decoration: none; - color: #fff; } - -.nav-box { - display: inline-block; - margin-top: 5px; - margin-bottom: 5px; - margin-left: 15px; - margin-bottom: 15px; - font-size: 1.2em; } - -.nav-box.register { - border: 1px solid #fff; - padding: 0 5px; - border-radius: 5px; } - -.team-box { - float: left; - margin: 5px; } - -.team-box img { - border-radius: 150px; } - -#contact { - width: 100%; - background-color: #f4f4f4; } - -form#contact input, textarea, select, btn-primary { - width: 100%; - max-width: 600px; - margin: 10px 0; - border-radius: 5px; - height: 50px; - padding: 5px; } - -form#contact textarea { - height: 150px; } - -form#contact input.btn.btn-primary { - max-width: 150px; } - -.center { - text-align: center; } - -@media (max-width: 1200px) { - body { - font-size: 20px; } - #main { - background-image: none; } - #why { - background-image: none; } - #how { - background-image: none; } - #where { - background-image: none; } - #fixedbtn-offer { - display: none; } - .event-box { - margin-left: 0; - margin-top: 40px; } - .left svg { - margin-top: 10px; } } - -@media (max-width: 992px) { - body { - font-size: 15px; } - p { - margin-bottom: 10px; } - h1.main-title { - font-size: 3em !important; } - div.left { - display: none; } - a#start { - display: none; } - div#footer { - background-color: #fff; - color: #333; } - img#logo { - width: 100px; } - #main, #why, #contact { - padding-top: 30px; } - .event-info h3 { - margin-bottom: 0px; - font-size: 1.3em; } - .event-info { - margin-left: 0; } - .event-box { - padding-top: 0px; - margin-top: 20px; } - .btn-primary { - font-size: 1.0em; } - #fixedbtn-up, #fixedbtn-reg, #fixedbtn-twitter, #fixedbtn-facebook, #fixedbtn-instagram, #fixedbtn-slack, #fixedbtn-github { - display: none; } - .nav-bottom { - display: none; - font-size: 1.5em; } - .sponsors img { - max-width: 200px; } - .support img { - max-width: 120px; } - .support { - text-align: cen center; } - .sponsors { - text-align: center; } } diff --git a/docs/css/social-btn.css b/docs/css/social-btn.css deleted file mode 100644 index 93e16f7..0000000 --- a/docs/css/social-btn.css +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Social Buttons for Bootstrap - * - * Copyright 2013-2016 Panayiotis Lipiridis - * Licensed under the MIT License - * - * https://github.com/lipis/bootstrap-social - */ - -.btn-social{position:relative;padding-left:44px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.btn-social>:first-child{position:absolute;left:0;top:0;bottom:0;width:32px;line-height:34px;font-size:1.6em;text-align:center;border-right:1px solid rgba(0,0,0,0.2)} -.btn-social.btn-lg{padding-left:61px}.btn-social.btn-lg>:first-child{line-height:45px;width:45px;font-size:1.8em} -.btn-social.btn-sm{padding-left:38px}.btn-social.btn-sm>:first-child{line-height:28px;width:28px;font-size:1.4em} -.btn-social.btn-xs{padding-left:30px}.btn-social.btn-xs>:first-child{line-height:20px;width:20px;font-size:1.2em} -.btn-social-icon{position:relative;padding-left:44px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:34px;width:34px;padding:0}.btn-social-icon>:first-child{position:absolute;left:0;top:0;bottom:0;width:32px;line-height:34px;font-size:1.6em;text-align:center;border-right:1px solid rgba(0,0,0,0.2)} -.btn-social-icon.btn-lg{padding-left:61px}.btn-social-icon.btn-lg>:first-child{line-height:45px;width:45px;font-size:1.8em} -.btn-social-icon.btn-sm{padding-left:38px}.btn-social-icon.btn-sm>:first-child{line-height:28px;width:28px;font-size:1.4em} -.btn-social-icon.btn-xs{padding-left:30px}.btn-social-icon.btn-xs>:first-child{line-height:20px;width:20px;font-size:1.2em} -.btn-social-icon>:first-child{border:none;text-align:center;width:100% !important} -.btn-social-icon.btn-lg{height:45px;width:45px;padding-left:0;padding-right:0} -.btn-social-icon.btn-sm{height:30px;width:30px;padding-left:0;padding-right:0} -.btn-social-icon.btn-xs{height:22px;width:22px;padding-left:0;padding-right:0} -.btn-adn{color:#fff;background-color:#d87a68;border-color:rgba(0,0,0,0.2)}.btn-adn:focus,.btn-adn.focus{color:#fff;background-color:#ce563f;border-color:rgba(0,0,0,0.2)} -.btn-adn:hover{color:#fff;background-color:#ce563f;border-color:rgba(0,0,0,0.2)} -.btn-adn:active,.btn-adn.active,.open>.dropdown-toggle.btn-adn{color:#fff;background-color:#ce563f;border-color:rgba(0,0,0,0.2)}.btn-adn:active:hover,.btn-adn.active:hover,.open>.dropdown-toggle.btn-adn:hover,.btn-adn:active:focus,.btn-adn.active:focus,.open>.dropdown-toggle.btn-adn:focus,.btn-adn:active.focus,.btn-adn.active.focus,.open>.dropdown-toggle.btn-adn.focus{color:#fff;background-color:#b94630;border-color:rgba(0,0,0,0.2)} -.btn-adn:active,.btn-adn.active,.open>.dropdown-toggle.btn-adn{background-image:none} -.btn-adn.disabled:hover,.btn-adn[disabled]:hover,fieldset[disabled] .btn-adn:hover,.btn-adn.disabled:focus,.btn-adn[disabled]:focus,fieldset[disabled] .btn-adn:focus,.btn-adn.disabled.focus,.btn-adn[disabled].focus,fieldset[disabled] .btn-adn.focus{background-color:#d87a68;border-color:rgba(0,0,0,0.2)} -.btn-adn .badge{color:#d87a68;background-color:#fff} -.btn-bitbucket{color:#fff;background-color:#205081;border-color:rgba(0,0,0,0.2)}.btn-bitbucket:focus,.btn-bitbucket.focus{color:#fff;background-color:#163758;border-color:rgba(0,0,0,0.2)} -.btn-bitbucket:hover{color:#fff;background-color:#163758;border-color:rgba(0,0,0,0.2)} -.btn-bitbucket:active,.btn-bitbucket.active,.open>.dropdown-toggle.btn-bitbucket{color:#fff;background-color:#163758;border-color:rgba(0,0,0,0.2)}.btn-bitbucket:active:hover,.btn-bitbucket.active:hover,.open>.dropdown-toggle.btn-bitbucket:hover,.btn-bitbucket:active:focus,.btn-bitbucket.active:focus,.open>.dropdown-toggle.btn-bitbucket:focus,.btn-bitbucket:active.focus,.btn-bitbucket.active.focus,.open>.dropdown-toggle.btn-bitbucket.focus{color:#fff;background-color:#0f253c;border-color:rgba(0,0,0,0.2)} -.btn-bitbucket:active,.btn-bitbucket.active,.open>.dropdown-toggle.btn-bitbucket{background-image:none} -.btn-bitbucket.disabled:hover,.btn-bitbucket[disabled]:hover,fieldset[disabled] .btn-bitbucket:hover,.btn-bitbucket.disabled:focus,.btn-bitbucket[disabled]:focus,fieldset[disabled] .btn-bitbucket:focus,.btn-bitbucket.disabled.focus,.btn-bitbucket[disabled].focus,fieldset[disabled] .btn-bitbucket.focus{background-color:#205081;border-color:rgba(0,0,0,0.2)} -.btn-bitbucket .badge{color:#205081;background-color:#fff} -.btn-dropbox{color:#fff;background-color:#1087dd;border-color:rgba(0,0,0,0.2)}.btn-dropbox:focus,.btn-dropbox.focus{color:#fff;background-color:#0d6aad;border-color:rgba(0,0,0,0.2)} -.btn-dropbox:hover{color:#fff;background-color:#0d6aad;border-color:rgba(0,0,0,0.2)} -.btn-dropbox:active,.btn-dropbox.active,.open>.dropdown-toggle.btn-dropbox{color:#fff;background-color:#0d6aad;border-color:rgba(0,0,0,0.2)}.btn-dropbox:active:hover,.btn-dropbox.active:hover,.open>.dropdown-toggle.btn-dropbox:hover,.btn-dropbox:active:focus,.btn-dropbox.active:focus,.open>.dropdown-toggle.btn-dropbox:focus,.btn-dropbox:active.focus,.btn-dropbox.active.focus,.open>.dropdown-toggle.btn-dropbox.focus{color:#fff;background-color:#0a568c;border-color:rgba(0,0,0,0.2)} -.btn-dropbox:active,.btn-dropbox.active,.open>.dropdown-toggle.btn-dropbox{background-image:none} -.btn-dropbox.disabled:hover,.btn-dropbox[disabled]:hover,fieldset[disabled] .btn-dropbox:hover,.btn-dropbox.disabled:focus,.btn-dropbox[disabled]:focus,fieldset[disabled] .btn-dropbox:focus,.btn-dropbox.disabled.focus,.btn-dropbox[disabled].focus,fieldset[disabled] .btn-dropbox.focus{background-color:#1087dd;border-color:rgba(0,0,0,0.2)} -.btn-dropbox .badge{color:#1087dd;background-color:#fff} -.btn-facebook{color:#fff;background-color:#3b5998;border-color:rgba(0,0,0,0.2)}.btn-facebook:focus,.btn-facebook.focus{color:#fff;background-color:#2d4373;border-color:rgba(0,0,0,0.2)} -.btn-facebook:hover{color:#fff;background-color:#2d4373;border-color:rgba(0,0,0,0.2)} -.btn-facebook:active,.btn-facebook.active,.open>.dropdown-toggle.btn-facebook{color:#fff;background-color:#2d4373;border-color:rgba(0,0,0,0.2)}.btn-facebook:active:hover,.btn-facebook.active:hover,.open>.dropdown-toggle.btn-facebook:hover,.btn-facebook:active:focus,.btn-facebook.active:focus,.open>.dropdown-toggle.btn-facebook:focus,.btn-facebook:active.focus,.btn-facebook.active.focus,.open>.dropdown-toggle.btn-facebook.focus{color:#fff;background-color:#23345a;border-color:rgba(0,0,0,0.2)} -.btn-facebook:active,.btn-facebook.active,.open>.dropdown-toggle.btn-facebook{background-image:none} -.btn-facebook.disabled:hover,.btn-facebook[disabled]:hover,fieldset[disabled] .btn-facebook:hover,.btn-facebook.disabled:focus,.btn-facebook[disabled]:focus,fieldset[disabled] .btn-facebook:focus,.btn-facebook.disabled.focus,.btn-facebook[disabled].focus,fieldset[disabled] .btn-facebook.focus{background-color:#3b5998;border-color:rgba(0,0,0,0.2)} -.btn-facebook .badge{color:#3b5998;background-color:#fff} -.btn-flickr{color:#fff;background-color:#ff0084;border-color:rgba(0,0,0,0.2)}.btn-flickr:focus,.btn-flickr.focus{color:#fff;background-color:#cc006a;border-color:rgba(0,0,0,0.2)} -.btn-flickr:hover{color:#fff;background-color:#cc006a;border-color:rgba(0,0,0,0.2)} -.btn-flickr:active,.btn-flickr.active,.open>.dropdown-toggle.btn-flickr{color:#fff;background-color:#cc006a;border-color:rgba(0,0,0,0.2)}.btn-flickr:active:hover,.btn-flickr.active:hover,.open>.dropdown-toggle.btn-flickr:hover,.btn-flickr:active:focus,.btn-flickr.active:focus,.open>.dropdown-toggle.btn-flickr:focus,.btn-flickr:active.focus,.btn-flickr.active.focus,.open>.dropdown-toggle.btn-flickr.focus{color:#fff;background-color:#a80057;border-color:rgba(0,0,0,0.2)} -.btn-flickr:active,.btn-flickr.active,.open>.dropdown-toggle.btn-flickr{background-image:none} -.btn-flickr.disabled:hover,.btn-flickr[disabled]:hover,fieldset[disabled] .btn-flickr:hover,.btn-flickr.disabled:focus,.btn-flickr[disabled]:focus,fieldset[disabled] .btn-flickr:focus,.btn-flickr.disabled.focus,.btn-flickr[disabled].focus,fieldset[disabled] .btn-flickr.focus{background-color:#ff0084;border-color:rgba(0,0,0,0.2)} -.btn-flickr .badge{color:#ff0084;background-color:#fff} -.btn-foursquare{color:#fff;background-color:#f94877;border-color:rgba(0,0,0,0.2)}.btn-foursquare:focus,.btn-foursquare.focus{color:#fff;background-color:#f71752;border-color:rgba(0,0,0,0.2)} -.btn-foursquare:hover{color:#fff;background-color:#f71752;border-color:rgba(0,0,0,0.2)} -.btn-foursquare:active,.btn-foursquare.active,.open>.dropdown-toggle.btn-foursquare{color:#fff;background-color:#f71752;border-color:rgba(0,0,0,0.2)}.btn-foursquare:active:hover,.btn-foursquare.active:hover,.open>.dropdown-toggle.btn-foursquare:hover,.btn-foursquare:active:focus,.btn-foursquare.active:focus,.open>.dropdown-toggle.btn-foursquare:focus,.btn-foursquare:active.focus,.btn-foursquare.active.focus,.open>.dropdown-toggle.btn-foursquare.focus{color:#fff;background-color:#e30742;border-color:rgba(0,0,0,0.2)} -.btn-foursquare:active,.btn-foursquare.active,.open>.dropdown-toggle.btn-foursquare{background-image:none} -.btn-foursquare.disabled:hover,.btn-foursquare[disabled]:hover,fieldset[disabled] .btn-foursquare:hover,.btn-foursquare.disabled:focus,.btn-foursquare[disabled]:focus,fieldset[disabled] .btn-foursquare:focus,.btn-foursquare.disabled.focus,.btn-foursquare[disabled].focus,fieldset[disabled] .btn-foursquare.focus{background-color:#f94877;border-color:rgba(0,0,0,0.2)} -.btn-foursquare .badge{color:#f94877;background-color:#fff} -.btn-github{color:#fff;background-color:#444;border-color:rgba(0,0,0,0.2)}.btn-github:focus,.btn-github.focus{color:#fff;background-color:#2b2b2b;border-color:rgba(0,0,0,0.2)} -.btn-github:hover{color:#fff;background-color:#2b2b2b;border-color:rgba(0,0,0,0.2)} -.btn-github:active,.btn-github.active,.open>.dropdown-toggle.btn-github{color:#fff;background-color:#2b2b2b;border-color:rgba(0,0,0,0.2)}.btn-github:active:hover,.btn-github.active:hover,.open>.dropdown-toggle.btn-github:hover,.btn-github:active:focus,.btn-github.active:focus,.open>.dropdown-toggle.btn-github:focus,.btn-github:active.focus,.btn-github.active.focus,.open>.dropdown-toggle.btn-github.focus{color:#fff;background-color:#191919;border-color:rgba(0,0,0,0.2)} -.btn-github:active,.btn-github.active,.open>.dropdown-toggle.btn-github{background-image:none} -.btn-github.disabled:hover,.btn-github[disabled]:hover,fieldset[disabled] .btn-github:hover,.btn-github.disabled:focus,.btn-github[disabled]:focus,fieldset[disabled] .btn-github:focus,.btn-github.disabled.focus,.btn-github[disabled].focus,fieldset[disabled] .btn-github.focus{background-color:#444;border-color:rgba(0,0,0,0.2)} -.btn-github .badge{color:#444;background-color:#fff} -.btn-google{color:#fff;background-color:#dd4b39;border-color:rgba(0,0,0,0.2)}.btn-google:focus,.btn-google.focus{color:#fff;background-color:#c23321;border-color:rgba(0,0,0,0.2)} -.btn-google:hover{color:#fff;background-color:#c23321;border-color:rgba(0,0,0,0.2)} -.btn-google:active,.btn-google.active,.open>.dropdown-toggle.btn-google{color:#fff;background-color:#c23321;border-color:rgba(0,0,0,0.2)}.btn-google:active:hover,.btn-google.active:hover,.open>.dropdown-toggle.btn-google:hover,.btn-google:active:focus,.btn-google.active:focus,.open>.dropdown-toggle.btn-google:focus,.btn-google:active.focus,.btn-google.active.focus,.open>.dropdown-toggle.btn-google.focus{color:#fff;background-color:#a32b1c;border-color:rgba(0,0,0,0.2)} -.btn-google:active,.btn-google.active,.open>.dropdown-toggle.btn-google{background-image:none} -.btn-google.disabled:hover,.btn-google[disabled]:hover,fieldset[disabled] .btn-google:hover,.btn-google.disabled:focus,.btn-google[disabled]:focus,fieldset[disabled] .btn-google:focus,.btn-google.disabled.focus,.btn-google[disabled].focus,fieldset[disabled] .btn-google.focus{background-color:#dd4b39;border-color:rgba(0,0,0,0.2)} -.btn-google .badge{color:#dd4b39;background-color:#fff} -.btn-instagram{color:#fff;background-color:#3f729b;border-color:rgba(0,0,0,0.2)}.btn-instagram:focus,.btn-instagram.focus{color:#fff;background-color:#305777;border-color:rgba(0,0,0,0.2)} -.btn-instagram:hover{color:#fff;background-color:#305777;border-color:rgba(0,0,0,0.2)} -.btn-instagram:active,.btn-instagram.active,.open>.dropdown-toggle.btn-instagram{color:#fff;background-color:#305777;border-color:rgba(0,0,0,0.2)}.btn-instagram:active:hover,.btn-instagram.active:hover,.open>.dropdown-toggle.btn-instagram:hover,.btn-instagram:active:focus,.btn-instagram.active:focus,.open>.dropdown-toggle.btn-instagram:focus,.btn-instagram:active.focus,.btn-instagram.active.focus,.open>.dropdown-toggle.btn-instagram.focus{color:#fff;background-color:#26455d;border-color:rgba(0,0,0,0.2)} -.btn-instagram:active,.btn-instagram.active,.open>.dropdown-toggle.btn-instagram{background-image:none} -.btn-instagram.disabled:hover,.btn-instagram[disabled]:hover,fieldset[disabled] .btn-instagram:hover,.btn-instagram.disabled:focus,.btn-instagram[disabled]:focus,fieldset[disabled] .btn-instagram:focus,.btn-instagram.disabled.focus,.btn-instagram[disabled].focus,fieldset[disabled] .btn-instagram.focus{background-color:#3f729b;border-color:rgba(0,0,0,0.2)} -.btn-instagram .badge{color:#3f729b;background-color:#fff} -.btn-linkedin{color:#fff;background-color:#007bb6;border-color:rgba(0,0,0,0.2)}.btn-linkedin:focus,.btn-linkedin.focus{color:#fff;background-color:#005983;border-color:rgba(0,0,0,0.2)} -.btn-linkedin:hover{color:#fff;background-color:#005983;border-color:rgba(0,0,0,0.2)} -.btn-linkedin:active,.btn-linkedin.active,.open>.dropdown-toggle.btn-linkedin{color:#fff;background-color:#005983;border-color:rgba(0,0,0,0.2)}.btn-linkedin:active:hover,.btn-linkedin.active:hover,.open>.dropdown-toggle.btn-linkedin:hover,.btn-linkedin:active:focus,.btn-linkedin.active:focus,.open>.dropdown-toggle.btn-linkedin:focus,.btn-linkedin:active.focus,.btn-linkedin.active.focus,.open>.dropdown-toggle.btn-linkedin.focus{color:#fff;background-color:#00405f;border-color:rgba(0,0,0,0.2)} -.btn-linkedin:active,.btn-linkedin.active,.open>.dropdown-toggle.btn-linkedin{background-image:none} -.btn-linkedin.disabled:hover,.btn-linkedin[disabled]:hover,fieldset[disabled] .btn-linkedin:hover,.btn-linkedin.disabled:focus,.btn-linkedin[disabled]:focus,fieldset[disabled] .btn-linkedin:focus,.btn-linkedin.disabled.focus,.btn-linkedin[disabled].focus,fieldset[disabled] .btn-linkedin.focus{background-color:#007bb6;border-color:rgba(0,0,0,0.2)} -.btn-linkedin .badge{color:#007bb6;background-color:#fff} -.btn-microsoft{color:#fff;background-color:#2672ec;border-color:rgba(0,0,0,0.2)}.btn-microsoft:focus,.btn-microsoft.focus{color:#fff;background-color:#125acd;border-color:rgba(0,0,0,0.2)} -.btn-microsoft:hover{color:#fff;background-color:#125acd;border-color:rgba(0,0,0,0.2)} -.btn-microsoft:active,.btn-microsoft.active,.open>.dropdown-toggle.btn-microsoft{color:#fff;background-color:#125acd;border-color:rgba(0,0,0,0.2)}.btn-microsoft:active:hover,.btn-microsoft.active:hover,.open>.dropdown-toggle.btn-microsoft:hover,.btn-microsoft:active:focus,.btn-microsoft.active:focus,.open>.dropdown-toggle.btn-microsoft:focus,.btn-microsoft:active.focus,.btn-microsoft.active.focus,.open>.dropdown-toggle.btn-microsoft.focus{color:#fff;background-color:#0f4bac;border-color:rgba(0,0,0,0.2)} -.btn-microsoft:active,.btn-microsoft.active,.open>.dropdown-toggle.btn-microsoft{background-image:none} -.btn-microsoft.disabled:hover,.btn-microsoft[disabled]:hover,fieldset[disabled] .btn-microsoft:hover,.btn-microsoft.disabled:focus,.btn-microsoft[disabled]:focus,fieldset[disabled] .btn-microsoft:focus,.btn-microsoft.disabled.focus,.btn-microsoft[disabled].focus,fieldset[disabled] .btn-microsoft.focus{background-color:#2672ec;border-color:rgba(0,0,0,0.2)} -.btn-microsoft .badge{color:#2672ec;background-color:#fff} -.btn-odnoklassniki{color:#fff;background-color:#f4731c;border-color:rgba(0,0,0,0.2)}.btn-odnoklassniki:focus,.btn-odnoklassniki.focus{color:#fff;background-color:#d35b0a;border-color:rgba(0,0,0,0.2)} -.btn-odnoklassniki:hover{color:#fff;background-color:#d35b0a;border-color:rgba(0,0,0,0.2)} -.btn-odnoklassniki:active,.btn-odnoklassniki.active,.open>.dropdown-toggle.btn-odnoklassniki{color:#fff;background-color:#d35b0a;border-color:rgba(0,0,0,0.2)}.btn-odnoklassniki:active:hover,.btn-odnoklassniki.active:hover,.open>.dropdown-toggle.btn-odnoklassniki:hover,.btn-odnoklassniki:active:focus,.btn-odnoklassniki.active:focus,.open>.dropdown-toggle.btn-odnoklassniki:focus,.btn-odnoklassniki:active.focus,.btn-odnoklassniki.active.focus,.open>.dropdown-toggle.btn-odnoklassniki.focus{color:#fff;background-color:#b14c09;border-color:rgba(0,0,0,0.2)} -.btn-odnoklassniki:active,.btn-odnoklassniki.active,.open>.dropdown-toggle.btn-odnoklassniki{background-image:none} -.btn-odnoklassniki.disabled:hover,.btn-odnoklassniki[disabled]:hover,fieldset[disabled] .btn-odnoklassniki:hover,.btn-odnoklassniki.disabled:focus,.btn-odnoklassniki[disabled]:focus,fieldset[disabled] .btn-odnoklassniki:focus,.btn-odnoklassniki.disabled.focus,.btn-odnoklassniki[disabled].focus,fieldset[disabled] .btn-odnoklassniki.focus{background-color:#f4731c;border-color:rgba(0,0,0,0.2)} -.btn-odnoklassniki .badge{color:#f4731c;background-color:#fff} -.btn-openid{color:#fff;background-color:#f7931e;border-color:rgba(0,0,0,0.2)}.btn-openid:focus,.btn-openid.focus{color:#fff;background-color:#da7908;border-color:rgba(0,0,0,0.2)} -.btn-openid:hover{color:#fff;background-color:#da7908;border-color:rgba(0,0,0,0.2)} -.btn-openid:active,.btn-openid.active,.open>.dropdown-toggle.btn-openid{color:#fff;background-color:#da7908;border-color:rgba(0,0,0,0.2)}.btn-openid:active:hover,.btn-openid.active:hover,.open>.dropdown-toggle.btn-openid:hover,.btn-openid:active:focus,.btn-openid.active:focus,.open>.dropdown-toggle.btn-openid:focus,.btn-openid:active.focus,.btn-openid.active.focus,.open>.dropdown-toggle.btn-openid.focus{color:#fff;background-color:#b86607;border-color:rgba(0,0,0,0.2)} -.btn-openid:active,.btn-openid.active,.open>.dropdown-toggle.btn-openid{background-image:none} -.btn-openid.disabled:hover,.btn-openid[disabled]:hover,fieldset[disabled] .btn-openid:hover,.btn-openid.disabled:focus,.btn-openid[disabled]:focus,fieldset[disabled] .btn-openid:focus,.btn-openid.disabled.focus,.btn-openid[disabled].focus,fieldset[disabled] .btn-openid.focus{background-color:#f7931e;border-color:rgba(0,0,0,0.2)} -.btn-openid .badge{color:#f7931e;background-color:#fff} -.btn-pinterest{color:#fff;background-color:#cb2027;border-color:rgba(0,0,0,0.2)}.btn-pinterest:focus,.btn-pinterest.focus{color:#fff;background-color:#9f191f;border-color:rgba(0,0,0,0.2)} -.btn-pinterest:hover{color:#fff;background-color:#9f191f;border-color:rgba(0,0,0,0.2)} -.btn-pinterest:active,.btn-pinterest.active,.open>.dropdown-toggle.btn-pinterest{color:#fff;background-color:#9f191f;border-color:rgba(0,0,0,0.2)}.btn-pinterest:active:hover,.btn-pinterest.active:hover,.open>.dropdown-toggle.btn-pinterest:hover,.btn-pinterest:active:focus,.btn-pinterest.active:focus,.open>.dropdown-toggle.btn-pinterest:focus,.btn-pinterest:active.focus,.btn-pinterest.active.focus,.open>.dropdown-toggle.btn-pinterest.focus{color:#fff;background-color:#801419;border-color:rgba(0,0,0,0.2)} -.btn-pinterest:active,.btn-pinterest.active,.open>.dropdown-toggle.btn-pinterest{background-image:none} -.btn-pinterest.disabled:hover,.btn-pinterest[disabled]:hover,fieldset[disabled] .btn-pinterest:hover,.btn-pinterest.disabled:focus,.btn-pinterest[disabled]:focus,fieldset[disabled] .btn-pinterest:focus,.btn-pinterest.disabled.focus,.btn-pinterest[disabled].focus,fieldset[disabled] .btn-pinterest.focus{background-color:#cb2027;border-color:rgba(0,0,0,0.2)} -.btn-pinterest .badge{color:#cb2027;background-color:#fff} -.btn-reddit{color:#000;background-color:#eff7ff;border-color:rgba(0,0,0,0.2)}.btn-reddit:focus,.btn-reddit.focus{color:#000;background-color:#bcddff;border-color:rgba(0,0,0,0.2)} -.btn-reddit:hover{color:#000;background-color:#bcddff;border-color:rgba(0,0,0,0.2)} -.btn-reddit:active,.btn-reddit.active,.open>.dropdown-toggle.btn-reddit{color:#000;background-color:#bcddff;border-color:rgba(0,0,0,0.2)}.btn-reddit:active:hover,.btn-reddit.active:hover,.open>.dropdown-toggle.btn-reddit:hover,.btn-reddit:active:focus,.btn-reddit.active:focus,.open>.dropdown-toggle.btn-reddit:focus,.btn-reddit:active.focus,.btn-reddit.active.focus,.open>.dropdown-toggle.btn-reddit.focus{color:#000;background-color:#98ccff;border-color:rgba(0,0,0,0.2)} -.btn-reddit:active,.btn-reddit.active,.open>.dropdown-toggle.btn-reddit{background-image:none} -.btn-reddit.disabled:hover,.btn-reddit[disabled]:hover,fieldset[disabled] .btn-reddit:hover,.btn-reddit.disabled:focus,.btn-reddit[disabled]:focus,fieldset[disabled] .btn-reddit:focus,.btn-reddit.disabled.focus,.btn-reddit[disabled].focus,fieldset[disabled] .btn-reddit.focus{background-color:#eff7ff;border-color:rgba(0,0,0,0.2)} -.btn-reddit .badge{color:#eff7ff;background-color:#000} -.btn-soundcloud{color:#fff;background-color:#f50;border-color:rgba(0,0,0,0.2)}.btn-soundcloud:focus,.btn-soundcloud.focus{color:#fff;background-color:#c40;border-color:rgba(0,0,0,0.2)} -.btn-soundcloud:hover{color:#fff;background-color:#c40;border-color:rgba(0,0,0,0.2)} -.btn-soundcloud:active,.btn-soundcloud.active,.open>.dropdown-toggle.btn-soundcloud{color:#fff;background-color:#c40;border-color:rgba(0,0,0,0.2)}.btn-soundcloud:active:hover,.btn-soundcloud.active:hover,.open>.dropdown-toggle.btn-soundcloud:hover,.btn-soundcloud:active:focus,.btn-soundcloud.active:focus,.open>.dropdown-toggle.btn-soundcloud:focus,.btn-soundcloud:active.focus,.btn-soundcloud.active.focus,.open>.dropdown-toggle.btn-soundcloud.focus{color:#fff;background-color:#a83800;border-color:rgba(0,0,0,0.2)} -.btn-soundcloud:active,.btn-soundcloud.active,.open>.dropdown-toggle.btn-soundcloud{background-image:none} -.btn-soundcloud.disabled:hover,.btn-soundcloud[disabled]:hover,fieldset[disabled] .btn-soundcloud:hover,.btn-soundcloud.disabled:focus,.btn-soundcloud[disabled]:focus,fieldset[disabled] .btn-soundcloud:focus,.btn-soundcloud.disabled.focus,.btn-soundcloud[disabled].focus,fieldset[disabled] .btn-soundcloud.focus{background-color:#f50;border-color:rgba(0,0,0,0.2)} -.btn-soundcloud .badge{color:#f50;background-color:#fff} -.btn-tumblr{color:#fff;background-color:#2c4762;border-color:rgba(0,0,0,0.2)}.btn-tumblr:focus,.btn-tumblr.focus{color:#fff;background-color:#1c2d3f;border-color:rgba(0,0,0,0.2)} -.btn-tumblr:hover{color:#fff;background-color:#1c2d3f;border-color:rgba(0,0,0,0.2)} -.btn-tumblr:active,.btn-tumblr.active,.open>.dropdown-toggle.btn-tumblr{color:#fff;background-color:#1c2d3f;border-color:rgba(0,0,0,0.2)}.btn-tumblr:active:hover,.btn-tumblr.active:hover,.open>.dropdown-toggle.btn-tumblr:hover,.btn-tumblr:active:focus,.btn-tumblr.active:focus,.open>.dropdown-toggle.btn-tumblr:focus,.btn-tumblr:active.focus,.btn-tumblr.active.focus,.open>.dropdown-toggle.btn-tumblr.focus{color:#fff;background-color:#111c26;border-color:rgba(0,0,0,0.2)} -.btn-tumblr:active,.btn-tumblr.active,.open>.dropdown-toggle.btn-tumblr{background-image:none} -.btn-tumblr.disabled:hover,.btn-tumblr[disabled]:hover,fieldset[disabled] .btn-tumblr:hover,.btn-tumblr.disabled:focus,.btn-tumblr[disabled]:focus,fieldset[disabled] .btn-tumblr:focus,.btn-tumblr.disabled.focus,.btn-tumblr[disabled].focus,fieldset[disabled] .btn-tumblr.focus{background-color:#2c4762;border-color:rgba(0,0,0,0.2)} -.btn-tumblr .badge{color:#2c4762;background-color:#fff} -.btn-twitter{color:#fff;background-color:#55acee;border-color:rgba(0,0,0,0.2)}.btn-twitter:focus,.btn-twitter.focus{color:#fff;background-color:#2795e9;border-color:rgba(0,0,0,0.2)} -.btn-twitter:hover{color:#fff;background-color:#2795e9;border-color:rgba(0,0,0,0.2)} -.btn-twitter:active,.btn-twitter.active,.open>.dropdown-toggle.btn-twitter{color:#fff;background-color:#2795e9;border-color:rgba(0,0,0,0.2)}.btn-twitter:active:hover,.btn-twitter.active:hover,.open>.dropdown-toggle.btn-twitter:hover,.btn-twitter:active:focus,.btn-twitter.active:focus,.open>.dropdown-toggle.btn-twitter:focus,.btn-twitter:active.focus,.btn-twitter.active.focus,.open>.dropdown-toggle.btn-twitter.focus{color:#fff;background-color:#1583d7;border-color:rgba(0,0,0,0.2)} -.btn-twitter:active,.btn-twitter.active,.open>.dropdown-toggle.btn-twitter{background-image:none} -.btn-twitter.disabled:hover,.btn-twitter[disabled]:hover,fieldset[disabled] .btn-twitter:hover,.btn-twitter.disabled:focus,.btn-twitter[disabled]:focus,fieldset[disabled] .btn-twitter:focus,.btn-twitter.disabled.focus,.btn-twitter[disabled].focus,fieldset[disabled] .btn-twitter.focus{background-color:#55acee;border-color:rgba(0,0,0,0.2)} -.btn-twitter .badge{color:#55acee;background-color:#fff} -.btn-vimeo{color:#fff;background-color:#1ab7ea;border-color:rgba(0,0,0,0.2)}.btn-vimeo:focus,.btn-vimeo.focus{color:#fff;background-color:#1295bf;border-color:rgba(0,0,0,0.2)} -.btn-vimeo:hover{color:#fff;background-color:#1295bf;border-color:rgba(0,0,0,0.2)} -.btn-vimeo:active,.btn-vimeo.active,.open>.dropdown-toggle.btn-vimeo{color:#fff;background-color:#1295bf;border-color:rgba(0,0,0,0.2)}.btn-vimeo:active:hover,.btn-vimeo.active:hover,.open>.dropdown-toggle.btn-vimeo:hover,.btn-vimeo:active:focus,.btn-vimeo.active:focus,.open>.dropdown-toggle.btn-vimeo:focus,.btn-vimeo:active.focus,.btn-vimeo.active.focus,.open>.dropdown-toggle.btn-vimeo.focus{color:#fff;background-color:#0f7b9f;border-color:rgba(0,0,0,0.2)} -.btn-vimeo:active,.btn-vimeo.active,.open>.dropdown-toggle.btn-vimeo{background-image:none} -.btn-vimeo.disabled:hover,.btn-vimeo[disabled]:hover,fieldset[disabled] .btn-vimeo:hover,.btn-vimeo.disabled:focus,.btn-vimeo[disabled]:focus,fieldset[disabled] .btn-vimeo:focus,.btn-vimeo.disabled.focus,.btn-vimeo[disabled].focus,fieldset[disabled] .btn-vimeo.focus{background-color:#1ab7ea;border-color:rgba(0,0,0,0.2)} -.btn-vimeo .badge{color:#1ab7ea;background-color:#fff} -.btn-vk{color:#fff;background-color:#587ea3;border-color:rgba(0,0,0,0.2)}.btn-vk:focus,.btn-vk.focus{color:#fff;background-color:#466482;border-color:rgba(0,0,0,0.2)} -.btn-vk:hover{color:#fff;background-color:#466482;border-color:rgba(0,0,0,0.2)} -.btn-vk:active,.btn-vk.active,.open>.dropdown-toggle.btn-vk{color:#fff;background-color:#466482;border-color:rgba(0,0,0,0.2)}.btn-vk:active:hover,.btn-vk.active:hover,.open>.dropdown-toggle.btn-vk:hover,.btn-vk:active:focus,.btn-vk.active:focus,.open>.dropdown-toggle.btn-vk:focus,.btn-vk:active.focus,.btn-vk.active.focus,.open>.dropdown-toggle.btn-vk.focus{color:#fff;background-color:#3a526b;border-color:rgba(0,0,0,0.2)} -.btn-vk:active,.btn-vk.active,.open>.dropdown-toggle.btn-vk{background-image:none} -.btn-vk.disabled:hover,.btn-vk[disabled]:hover,fieldset[disabled] .btn-vk:hover,.btn-vk.disabled:focus,.btn-vk[disabled]:focus,fieldset[disabled] .btn-vk:focus,.btn-vk.disabled.focus,.btn-vk[disabled].focus,fieldset[disabled] .btn-vk.focus{background-color:#587ea3;border-color:rgba(0,0,0,0.2)} -.btn-vk .badge{color:#587ea3;background-color:#fff} -.btn-yahoo{color:#fff;background-color:#720e9e;border-color:rgba(0,0,0,0.2)}.btn-yahoo:focus,.btn-yahoo.focus{color:#fff;background-color:#500a6f;border-color:rgba(0,0,0,0.2)} -.btn-yahoo:hover{color:#fff;background-color:#500a6f;border-color:rgba(0,0,0,0.2)} -.btn-yahoo:active,.btn-yahoo.active,.open>.dropdown-toggle.btn-yahoo{color:#fff;background-color:#500a6f;border-color:rgba(0,0,0,0.2)}.btn-yahoo:active:hover,.btn-yahoo.active:hover,.open>.dropdown-toggle.btn-yahoo:hover,.btn-yahoo:active:focus,.btn-yahoo.active:focus,.open>.dropdown-toggle.btn-yahoo:focus,.btn-yahoo:active.focus,.btn-yahoo.active.focus,.open>.dropdown-toggle.btn-yahoo.focus{color:#fff;background-color:#39074e;border-color:rgba(0,0,0,0.2)} -.btn-yahoo:active,.btn-yahoo.active,.open>.dropdown-toggle.btn-yahoo{background-image:none} -.btn-yahoo.disabled:hover,.btn-yahoo[disabled]:hover,fieldset[disabled] .btn-yahoo:hover,.btn-yahoo.disabled:focus,.btn-yahoo[disabled]:focus,fieldset[disabled] .btn-yahoo:focus,.btn-yahoo.disabled.focus,.btn-yahoo[disabled].focus,fieldset[disabled] .btn-yahoo.focus{background-color:#720e9e;border-color:rgba(0,0,0,0.2)} -.btn-yahoo .badge{color:#720e9e;background-color:#fff} diff --git a/docs/css/style.css b/docs/css/style.css deleted file mode 100644 index 0fa690b..0000000 --- a/docs/css/style.css +++ /dev/null @@ -1,35 +0,0 @@ -@import url("https://fonts.googleapis.com/css?family=Heebo:100,200,400,600,900"); -body, .event-box { - font-family: 'Heebo', sans-serif; } - -.navbar { - font-family: 'Heebo', sans-serif; - font-weight: 400; } - -h1.big-title { - font-family: 'Heebo', sans-serif; - font-weight: 900; - font-size: 3em; } - -h1.main-title { - font-size: 4em; } - -p.event a { - color: #f4f4f4; } - -p.event { - font-size: 1em; } - -p.resource { - color: #333; } - -.btn-primary { - margin: 5px; - width: 300px; - font-size: 1.5em; } - -.btn-primary:hover { - background-color: #da6314; } - -a.btn-primary { - text-decoration: none; } diff --git a/docs/footer.html b/docs/footer.html deleted file mode 100644 index 4b82d73..0000000 --- a/docs/footer.html +++ /dev/null @@ -1,2 +0,0 @@ - -

© HiPy 2019

\ No newline at end of file diff --git a/docs/how.html b/docs/how.html deleted file mode 100644 index f8e05ad..0000000 --- a/docs/how.html +++ /dev/null @@ -1,13 +0,0 @@ - -
-
-

-- What?

-

We deliver bespoke coding workshops

-

Highly interactive sessions taylored to the needs of your cohort.

-

- We are experts at providing introductory training sessions for the - Python coding language. Our workshops rely heavily on a learn by doing approach to coding. -

-

All students who attend our workshops join our cdtPy network and receive support from us throughout their doctoral training.

Get in contact with us now to book your workshop. -
-
\ No newline at end of file diff --git a/docs/img/card.png b/docs/img/card.png deleted file mode 100644 index 81a8a60..0000000 Binary files a/docs/img/card.png and /dev/null differ diff --git a/docs/img/hipy_logo.jpg b/docs/img/hipy_logo.jpg deleted file mode 100644 index dd5fd4a..0000000 Binary files a/docs/img/hipy_logo.jpg and /dev/null differ diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 7e8320b..0000000 --- a/docs/index.html +++ /dev/null @@ -1,205 +0,0 @@ - - - - - - HiPy - Come All. Learn Code. - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
-

Join the Hive.

-

Come All. Learn Code.


-

HiPy is an open, grass-roots community of people dedicated to - introducing anyone and everyone to coding. -

-

All our events are for absolute beginners and are designed specifically to get you coding as - quickly as possible with zero nonsense. -

-
- -
- -
-
-
-
- -
-
-
-
-
-
-

Contact

-

Got a question? Complete the form below. We'll get back to you.


-
-
-
-
-
-
- -

-
-
-
-
-
-
- -
-
-
-
-
Contact Us
-
-
-
-
-
-
-
- - - - - - - - - - - \ No newline at end of file diff --git a/docs/jade/contact.jade b/docs/jade/contact.jade deleted file mode 100644 index 98286f7..0000000 --- a/docs/jade/contact.jade +++ /dev/null @@ -1,18 +0,0 @@ -.row.wrapper - .col.col-lg-12.title.headline - h1.big-title - | Contact - p - | Got a question? Complete the form below. We'll get back to you. - br - .col.col-lg-12 - form#contact(action='https://formspree.io/R.Treharne@liverpool.ac.uk', method='POST') - input(type='text', name='name', placeholder='Name') - br - input(type='email', name='_replyto', placeholder='Email') - br - textarea(type='tex', name='_message', placeholder='Type message here ...' ) - br - input.btn.btn-primary(type='submit', value='Send') - - br diff --git a/docs/jade/footer.jade b/docs/jade/footer.jade deleted file mode 100644 index d3e7059..0000000 --- a/docs/jade/footer.jade +++ /dev/null @@ -1,4 +0,0 @@ - -img#logo(src="img/hipy_logo.jpg") - -p © HiPy 2019 diff --git a/docs/jade/index.jade b/docs/jade/index.jade deleted file mode 100644 index 4c71084..0000000 --- a/docs/jade/index.jade +++ /dev/null @@ -1,160 +0,0 @@ -doctype html -html(lang='en') - head - meta(http-equiv='content-type', content='text/html; charset=UTF-8') - meta(charset='utf-8') - title HiPy - Come All. Learn Code. - meta(name='viewport', content='width=device-width, initial-scale=1, maximum-scale=1') - meta(name='description', content='HiPy is an open, welcoming grass-roots initiative that aims to introduce anyone and everyone to Python. For free.') - meta(name='keywords', content='Python, coding, Liverpool, community, data, employability') - meta(property='og:image', content='https://github.com/rtreharne/HiPyProject/blob/master/docs/img/card.png?raw=true') - meta(property='og:description', content='HiPy is an open, welcoming grass-roots initiative that aims to introduce anyone and everyone to Python. For free.') - meta(property='og:title', content='HiPy - Come All. Learn Code. For Free.') - - meta(name='twitter:card', content='summary_large_image') - meta(name='twitter:site', content='@hipyliv') - meta(name='twitter:title', content='HiPy - Come All. Learn Code. For Free') - meta(name='twitter:description', content='HiPy is an open, welcoming, grass-roots community of people at the Universty of Liverpool who want to increase their employability by learning coding skills. Our events are open to everyone and are absolutely free') - meta(name='twitter:image', content='https://pbs.twimg.com/profile_images/750461851385946112/AXY6sC_C_400x400.jpg') - meta(name='twitter:image:alt', content='HiPy logo') - - - link(href='//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css', rel='stylesheet') - link(href="css/basic.css", rel="stylesheet") - link(href="css/style.css", rel="stylesheet") - - //if lt IE 9 - script(src='//html5shim.googlecode.com/svn/trunk/html5.js') - - body - // - .navbar.navbar-default.navbar-fixed-top - .container - .navbar-header - - button.navbar-toggle(type='button', data-toggle='collapse', data-target='.navbar-collapse') - - span.icon-bar - span.icon-bar - span.icon-bar - a.navbar-brand(href='#main') - b cdt - font.pink Py - font(style="font-size:0.5em") .org - .collapse.navbar-collapse - ul.nav.navbar-nav.navbar-right - li - a(href='#why') why - li - a(href='#how') what - - li - a(href='#contact') contact - - - // - - .container#main.full-height.vertical-center.headline - .row - .col.col-lg-offset-2.col-lg-8 - .text-left - include main.jade - - - .container#why.full-height.vertical-center - .row - .col.col-lg-offset-1.col-lg-10 - .text-left - include why.jade - - .container#contact.full-height.vertical-center - .row - .col.col-lg-offset-1.col-lg-10 - .text-left - include contact.jade - - - - - .container#footer.vertical-center - .row - .col.col-lg-12 - .text-center - include footer.jade - - a(href='#main') - #fixedbtn-up - .inner-fixedbtn-up - i.fas.fa-arrow-up.fa-2x - - a(href='#contact') - #fixedbtn-reg - .inner-fixedbtn-reg Contact Us - - a(href="https://twitter.com/hipyliv" target="_blank") - #fixedbtn-twitter - .i.fab.fa-twitter.fa-2x - - a(href="https://teams.microsoft.com/l/team/19%3a967e532393b94c7a91f7980cb7af2015%40thread.skype/conversations?groupId=d954ee73-10cf-4309-add7-6ca2f5161239&tenantId=53255131-b129-4010-86e1-474bfd7e8076" target="_blank") - #fixedbtn-github - .i.fas.fa-users.fa-2x - - - - - - .nav-bottom - a(href="https://twitter.com/hipyliv" target="_blank") - .nav-box - .i.fab.fa-twitter - - a(href="https://github.com/HiPyLiv/HiPyProject" target="_blank") - .nav-box - .i.fab.fa-github - - a(href="#contact") - .nav-box - .i.fa.fa-envelope - - a(href="#main") - .nav-box - .i.fas.fa-arrow-up - - - - - - - script(type='text/javascript', src='//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js') - script(type='text/javascript', src='//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js') - script(type='text/javascript', src='js/scrolling.js') - script(defer='', src='https://use.fontawesome.com/releases/v5.0.8/js/all.js') - // JavaScript jQuery code from Bootply.com editor - script(type='text/javascript'). - $(document).ready(function() { - }); - script. - var right = $(".right-bg"); - var left = $(".left-bg"); - right.css({ - "background-position": (right.width()*.66) + "px " + "0px" - }); - left.css({ - "background-position": (-left.width()*.66) + "px " + "0px" - }); - script. - $("#sat-btn").click(function(){ - $("#saturday").show(); - $("#friday").hide(); - $("#sunday").hide(); - }); - $("#fri-btn").click(function(){ - $("#friday").show(); - $("#saturday").hide(); - $("#sunday").hide(); - }); - $("#sun-btn").click(function(){ - $("#saturday").hide(); - $("#friday").hide(); - $("#sunday").show(); - }); diff --git a/docs/jade/main.jade b/docs/jade/main.jade deleted file mode 100644 index fcd552b..0000000 --- a/docs/jade/main.jade +++ /dev/null @@ -1,54 +0,0 @@ -.row.wrapper - .col.col-lg-6.title.headline - h1.big-title.main-title - | Join the - font.pink Hive - | . - p - b Come All. Learn Code. - br - - p - b HiPy - | is an open, grass-roots community of people dedicated to - | introducing - b anyone - | and - b everyone - | to coding. - p - | All our events are for - b absolute beginners - | and are designed specifically to get you coding as - | quickly as possible with zero nonsense. - - - - - .col.col-lg-6.title.headline - h2.big-title Upcoming Events - p.event Register now - br - - p.event - a(href="https://libcal.liverpool.ac.uk/event/3444530", target="_blank") - b 28 Feb 2020. - | 12.00 - 13-00. - b Python for Lunch. - - p.event - a(href="https://www.eventbrite.com/e/hipy-tickets-72762315043", target="_blank") - b 25 Mar 2020. - | 17.00 - 19-00. - b Intro to Python. - - p.event - a(href="https://www.eventbrite.com/e/titanic-an-introduction-to-data-science-and-machine-learning-using-python-tickets-91575658259", target="_blank") - b 25 Mar 2020. - | 17.00 - 19-00. - b Intro to Data Science and Machine Learning. -.row.wrapper - .col.col-lg-12.center - br - a.btn-primary#start( href="#why" ) Start Coding - a.btn-primary#menu( href="https://forms.office.com/Pages/ResponsePage.aspx?id=MVElUymxEECG4UdL_X6AdnPuVNnPEAlDrddsovUWEjlURFRQN0lBMFZLMjRBUVExWVpYMERZRE03WSQlQCN0PWcu", target="_blank" ) Play my song diff --git a/docs/jade/why.jade b/docs/jade/why.jade deleted file mode 100644 index 099d223..0000000 --- a/docs/jade/why.jade +++ /dev/null @@ -1,35 +0,0 @@ -.row - .col.col-lg-12.headline - - h1.big-title - | Stop faffing. Start coding. - - .col.col-lg-9 - br - iframe(src='https://trinket.io/embed/python3/0c996d80ec?showInstructions=true', width='100%', height='600px', frameborder='0', marginwidth='0', marginheight='0', allowfullscreen='') - .col.col-lg-3 - h2 Resources - p - a(href="https://colab.research.google.com/drive/1XpiY4CrM1bH521VNWouqx-M52QBa8XQS" target="_blnank") - | Intro to Python - p - a(href="https://github.com/rebeccabilbro/titanic" target="_blank") - | TITANIC: Intro to Data Science and Machine Learning - p - a(href="https://www.youtube.com/playlist?list=PLqzoL9-eJTNBDdKgJgJzaQcY6OXmsXAHU" target="_blank") - | R Coding and Statistics - p - a(href="https://nbviewer.jupyter.org/github/HiPyLiv/HiPyProject/blob/master/%5BBASICS%5D%20Numpy%20and%20Pandas/Numpy%20and%20Pandas.ipynb" target="_blank") - | Numpy and Pandas - p - a(href="https://nbviewer.jupyter.org/github/HiPyLiv/HiPyProject/blob/master/%5BVISUALISATION%5D%20A%20Deeper%20Look%20Into%20Matplotlib/A%20Deeper%20Look%20Into%20Matplotlib.ipynb" target="_blank") - | A deeper look at matplotlib - p - a(href="https://nbviewer.jupyter.org/github/HiPyLiv/HiPyProject/blob/master/%5BSOURCING%5D%20Importing%20Data%20From%20Files/Importing%20Files%20From%20Files.ipynb" target="_blank") - | Importing data from files - p - a(href="https://nbviewer.jupyter.org/github/HiPyLiv/HiPyProject/blob/master/%5BSOURCING%5D%20Importing%20Data%20From%20The%20Web/Importing%20Data%20From%20The%20Web.ipynb" target="_blank") - | Importing data from the Web - p - a(href="https://github.com/HiPyLiv/HiPyProject" target="_blank") - | ... more diff --git a/docs/js/agency.js b/docs/js/agency.js deleted file mode 100644 index fb9a36c..0000000 --- a/docs/js/agency.js +++ /dev/null @@ -1,33 +0,0 @@ -// Agency Theme JavaScript - -(function($) { - "use strict"; // Start of use strict - - // jQuery for page scrolling feature - requires jQuery Easing plugin - $('a.page-scroll').bind('click', function(event) { - var $anchor = $(this); - $('html, body').stop().animate({ - scrollTop: ($($anchor.attr('href')).offset().top - 50) - }, 1250, 'easeInOutExpo'); - event.preventDefault(); - }); - - // Highlight the top nav as scrolling occurs - $('body').scrollspy({ - target: '.navbar-fixed-top', - offset: 51 - }); - - // Closes the Responsive Menu on Menu Item Click - $('.navbar-collapse ul li a').click(function(){ - $('.navbar-toggle:visible').click(); - }); - - // Offset for Main Navigation - $('#mainNav').affix({ - offset: { - top: 100 - } - }) - -})(jQuery); // End of use strict diff --git a/docs/js/scrolling.js b/docs/js/scrolling.js deleted file mode 100644 index bfe7be4..0000000 --- a/docs/js/scrolling.js +++ /dev/null @@ -1,64 +0,0 @@ -// Select all links with hashes -$('a[href*="#"]') - // Remove links that don't actually link to anything - .not('[href="#"]') - .not('[href="#0"]') - .click(function(event) { - // On-page links - if ( - location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') - && - location.hostname == this.hostname - ) { - // Figure out element to scroll to - var target = $(this.hash); - target = target.length ? target : $('[name=' + this.hash.slice(1) + ']'); - // Does a scroll target exist? - if (target.length) { - // Only prevent default if animation is actually gonna happen - event.preventDefault(); - $('html, body').animate({ - scrollTop: target.offset().top - }, 1000, function() { - // Callback after animation - // Must change focus! - var $target = $(target); - $target.focus(); - if ($target.is(":focus")) { // Checking if the target was focused - return false; - } else { - $target.attr('tabindex','-1'); // Adding tabindex for elements not focusable - $target.focus(); // Set focus again - }; - }); - } - } - }); - -var isVisible = false; -$(window).scroll(function(){ - var shouldBeVisible = $(window).scrollTop()>500; - if ($(window).width() > 992) { - if (shouldBeVisible && !isVisible) { - isVisible = true; - $('#fixedbtn-up').show(); - $('#fixedbtn-reg').show(); - } else if (isVisible && !shouldBeVisible) { - isVisible = false; - $('#fixedbtn-up').hide(); - $('#fixedbtn-reg').hide(); - } - - } - else { - var shouldBeVisible = $(window).scrollTop()>200; - if (shouldBeVisible && !isVisible) { - isVisible = true; - $('.nav-bottom').show(); - } else if (isVisible && !shouldBeVisible) { - isVisible = false; - $('.nav-bottom').hide(); - } - - } -}); diff --git a/docs/main.html b/docs/main.html deleted file mode 100644 index e9626d3..0000000 --- a/docs/main.html +++ /dev/null @@ -1,23 +0,0 @@ - -
-
-

Join the Hive.

-

Come All. Learn Code.


-

HiPy is an open, grass-roots community of people dedicated to - introducing anyone and everyone to coding. -

-

All our events are for absolute beginners and are designed specifically to get you coding as - quickly as possible with zero nonsense. -

-
- -
- \ No newline at end of file diff --git a/docs/programme.html b/docs/programme.html deleted file mode 100644 index 1687bf0..0000000 --- a/docs/programme.html +++ /dev/null @@ -1,10 +0,0 @@ - -
-
-

-- Why?

-

Writing your thesis is tough.

-

Sometimes it's hard to get motivated. That's where we come in.

-

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas semper enim a eros accumsan, vulputate imperdiet turpis blandit. Suspendisse sed purus nec elit elementum tempus.

-
-
-
\ No newline at end of file diff --git a/docs/register.html b/docs/register.html deleted file mode 100644 index 93dc203..0000000 --- a/docs/register.html +++ /dev/null @@ -1,4 +0,0 @@ - -

register


-

Register now using Eventbrite


-

Are you a Centre for Doctoral Training or another cohort based Centre?

Get in contact now for a quote with a group discount.

\ No newline at end of file diff --git a/docs/scss/_buttons.scss b/docs/scss/_buttons.scss deleted file mode 100644 index 20fe55e..0000000 --- a/docs/scss/_buttons.scss +++ /dev/null @@ -1,16 +0,0 @@ -.btn-primary { - background-color: transparent; - border: 2px white solid; - border-radius: 5px; - height: 100px; - width: 250px; - line-height: 100px; - padding:initial; - font-size: 1.5em; - text-align: center; -} - -.btn-primary:hover { - background-color: transparent; - border: 2px white solid; -} diff --git a/docs/scss/_functions.scss b/docs/scss/_functions.scss deleted file mode 100644 index 4e6578d..0000000 --- a/docs/scss/_functions.scss +++ /dev/null @@ -1,8 +0,0 @@ -// Functions -@function set-text-color($bg-color){ - @if(lightness($bg-color) > 50) { - @return #000; - } @else { - @return #fff; - } -} diff --git a/docs/scss/_navbar.scss b/docs/scss/_navbar.scss deleted file mode 100644 index 0596cf1..0000000 --- a/docs/scss/_navbar.scss +++ /dev/null @@ -1,86 +0,0 @@ -/* NAVBAR */ - -.navbar-custom { - background-color: #222222; - border-color: transparent; -} -.navbar-custom .navbar-brand { - color: #fff; - font-family: 'Archivo', sans-serif; - font-size: 2em; - letter-spacing: 1px; -} -.navbar-custom .navbar-brand:hover, -.navbar-custom .navbar-brand:focus, -.navbar-custom .navbar-brand:active, -.navbar-custom .navbar-brand.active { - color: #fff; -} -.navbar-custom .navbar-collapse { - border-color: rgba(255, 255, 255, 0.02); -} -.navbar-custom .navbar-toggle { - background-color: #075563; - border-color: #fff; - font-family: 'Archivo', sans-serif; - text-transform: none; - color: white; - font-size: 35px; -} -.navbar-custom .navbar-toggle:hover, -.navbar-custom .navbar-toggle:focus { - background-color: #fff; -} -.navbar-custom .nav li a { - font-family: 'Archivo', sans-serif; - //text-transform: uppercase; - font-weight: 700; - letter-spacing: 1px; - color: #fff; - font-size: 1.0em;; -} -.navbar-custom .nav li a:hover, -.navbar-custom .nav li a:focus { - color: #00d9ff; - outline: none; -} -.navbar-custom .navbar-nav > .active > a { - border-radius: 0; - color: white; - background-color: #00d9ff -} -.navbar-custom .navbar-nav > .active > a:hover, -.navbar-custom .navbar-nav > .active > a:focus { - color: white; - background-color: #00d9ff; -} -@media (min-width: 768px) { - .navbar-custom { - background-color: transparent; - padding: 25px 0; - -webkit-transition: padding 0.3s; - -moz-transition: padding 0.3s; - transition: padding 0.3s; - border: none; - } - .navbar-custom .navbar-brand { - font-size: 2em; - -webkit-transition: all 0.3s; - -moz-transition: all 0.3s; - transition: all 0.3s; - } - .navbar-custom .navbar-nav > .active > a { - border-radius: 3px; - } - - -} -@media (min-width: 768px) { - .navbar-custom.affix { - background-color: #222222; - padding: 10px 0; - } - .navbar-custom.affix .navbar-brand { - font-size: 1.5em; - } -} diff --git a/docs/scss/_variables.scss b/docs/scss/_variables.scss deleted file mode 100644 index 139ed03..0000000 --- a/docs/scss/_variables.scss +++ /dev/null @@ -1,13 +0,0 @@ -// Variables -$body-bg: #fff; -$main-font: 'Arial'; - -$primary-color: #fff; -$secondary-color: #ff873a; -$light-color: #f4f4f4; -$dark-color: #333; -$highlight: #ffe9d3; -$highlight-hover: #da6314; - -$container: 960px; -$section-padding: 50px; diff --git a/docs/scss/basic.scss b/docs/scss/basic.scss deleted file mode 100644 index b695d42..0000000 --- a/docs/scss/basic.scss +++ /dev/null @@ -1,536 +0,0 @@ -@import 'variables.scss'; - -*:focus { - outline: none; -} -.navbar { - font-size: 1.2em; -} - -.navbar-brand{ - font-size: 1.2em; - -} -.title { - white-space: normal; -} - -.sponsors img, .support img { - margin-right: 5px; - margin-bottom: 5px; -} - -.sponsors img { - max-width: 250px; -} - -.support img { - max-width: 150px; -} - - -hr.style-two { - border: 0; - height: 3px; - background-image: linear-gradient(to right, rgba(0, 0, 0, 0), $highlight, rgba(0, 0, 0, 0)); - margin-left: 25%; - margin-right: 25%; - margin-top: 75px; - margin-bottom: 75px; -} - -body { - font-size: 18px; -} - -.full-height { - min-height: 100vh; -} - -.headline { - padding-top: 5px; -} - -h1.big-title { - font-size: 4em; - margin-top: 10px; -} - -font.pink { - color: $highlight -} -.vertical-center { - min-height: 100%; /* Fallback for browsers do NOT support vh unit */ - min-height: 100vh; /* These two lines are counted as one :-) */ - - display: flex; - align-items: center; -} - -.row { - width: 100%; - margin:0; -} - - - -span.page-info { - font-size: 1.3em; - margin-top: 20px; - margin-bottom: 20px; - display: block; -} - -.btn-info{ - background-color:transparent; - font-size: 1.3em; - border-radius: 0px; - border: 2px grey solid; - color: grey; -} - -.google-maps { - position: relative; - padding-bottom: 75%; // This is the aspect ratio - height: 0; - overflow: hidden; -} -.google-maps iframe { - position: absolute; - top: 0; - left: 0; - width: 100% !important; - min-height: 500px; -} - -.event-box { - display: table; - padding-top: 100px; -} - -.event-box-line { - display: table-cell; - vertical-align: middle; - -} - -.event-info { - float: right; - margin: 10px; -} - -.event-info h3, p { - margin-top: 0px; - margin-bottom: 10px; -} - -.left { - float: left; - margin: 10px; - line-height: 100%; -} - - -.wrapper { - display: inline-block; - white-space: nowrap; -} - -.block { - white-space: normal; - vertical-align: middle; - float: none; - -} - -.image { - max-height: 100%; - max-width: 50%; -} - -#main { - //background-image: url('../img/main-bg-2.jpg'); - width: 100%; - ////background-repeat: no-repeat; - ///background-position: center; - background-color: $secondary-color -} - -#support h1.big-title { - font-size: 2em; -} - -#why { - //background-image: url('../img/why.jpg'); - width: auto; - background-repeat: no-repeat; - background-size:contain; -} - -#how { - background-image: url('../img/what.jpg'); - width: auto; - background-repeat: no-repeat; -} - - -#footer { - background-image: url('../img/footer-bg.jpg'); - width: auto; - background-repeat: no-repeat; - color: $dark-color; - padding: 100px; -} - -#footer img{ - max-width: 200px; -} - -#footer.vertical-center { - min-height: 0; - height: auto; -} - -.parallax { - - - /* Set a specific height */ - - /* Create the parallax scrolling effect */ - background-attachment: fixed; - background-size: cover; -} - - -.left { - line-height: 0; - margin: 0; -} - -.slider { - margin-top: 20px; -} - -.btn-primary { - font-family: 'Heebo', sans-serif; - color: $light-color; - background-color: $dark-color; - margin-top: 20px; - margin-bottom: 20px; - border-color: $highlight; - border-radius: 5px; - padding: 10px; - -webkit-animation: btnWiggle 5s infinite; - -moz-animation: btnWiggle 5s infinite; - -o-animation: btnWiggle 5s infinite; - animation: btnWiggle 5s infinite; -} - -.programme-btn:focus { - outline-color: blue !important; -} - -.btn-primary:hover { - background-color: $highlight-hover; - border-color: $highlight-hover; -} - -.tg { - border-collapse:collapse; - border-spacing:10px; - width:100%; -} -.tg td { - font-family:'Heebo', sans-serif; - font-size:1em; - padding: 20px 20px; - border-style:solid; - border-width:3px; - overflow:hidden; - word-break:normal; - border-left: none; - border-right: none; - -} -.tg th { - font-family:'Heebo', sans-serif; - font-size:1em;font-weight:bold; - padding: 20px 20px; - border-style:solid; - border-width:1px; - overflow:hidden; - word-break:normal; - border-left: none; - border-right: none; -} - -.tg .tg-yw4l{ - vertical-align:top -} - -tr.head { - background-color: $dark-color; - color: $primary-color; -} - -tr.write { - color: $highlight; -} - -table#sunday, table#saturday { - display: none; -} - -#fixedbtn-up, #fixedbtn-reg, #fixedbtn-twitter, #fixedbtn-facebook, #fixedbtn-instagram, #fixedbtn-slack, #fixedbtn-github, #fixedbtn-teams .nav-bottom { - position: fixed; - bottom: 20px; - right: 20px; - background-color: $dark-color; - color: $light-color; - font-size: 0.9em; - padding: 10px 10px; - width: 50px; - height: 50px; - border-radius: 50px; - text-align: center; - padding: 5px; - margin: 0px; - display: none; -} - -#fixedbtn-twitter { - right: 20px; - bottom: 140px; - display: block; -} - -#fixedbtn-instagram { - right: 20px; - top: 285px; - display: block; -} - -#fixedbtn-teams { - right: 20px; - top: 350px; - display: block; -} - -#fixedbtn-github { - right: 20px; - bottom: 80px; - display: block; -} - -#fixedbtn-twitter svg, #fixedbtn-facebook, #fixedbtn-slack svg, #fixedbtn-github svg, #fixedbtn-instagram svg { - padding-top: 5px; - margin-top: 2px; -} - -.inner-fixedbtn-up, .inner-fixedbtn-reg, .inner-fixedbtn-twitter, .inner-fixedbtn-facebook, .inner-fixedbtn-instagram { - line-height: 50px; -} - -#fixedbtn-reg { - right: 80px; - width: 200px; - border-radius: 5px; - font-size: 1.2em; - line-height: 50px; - margin: 0px; - padding: 0px; - display: none; -} - -#fixedbtn-offer { - width: 250px; - height: 250px; - border-radius: 250px; - display: table; - transform: rotate(20deg); - background-color: $highlight; - color: $primary-color; - font-size: 1.0em; - padding: 10px 10px; - text-align: center; - padding: 5px; - margin: 0px; - margin-top: 2px; - line-height: 1.2em; -} - -#fixedbtn-offer font.small { - font-size: 0.6em; -} -#fixedbtn-offer font.large { - font-size: 3em; - line-height:1.0em; -} - -.inner-fixedbtn-offer { - display: table-cell; - vertical-align: middle; -} - -.nav-bottom { - bottom: 0px; - right: 0px; - left: 0px; - height: 55px; - width: 100%; - border-radius: 0px; - padding: 0px; - margin: 0px; - display: none; - -} - -.nav-bottom a { - text-decoration: none; - color: $primary-color -} - -.nav-box { - display: inline-block; - margin-top: 5px; - margin-bottom: 5px; - margin-left: 15px; - margin-bottom: 15px; - font-size: 1.2em; -} - -.nav-box.register { - border: 1px solid $primary-color; - padding: 0 5px; - border-radius: 5px; - -} - -.team-box { - float: left; - margin: 5px; -} - -.team-box img { - border-radius: 150px; -} - -//CONTACT FORM - -#contact { - width: 100%; - background-color: $light-color; -} - -form#contact input, textarea, select, btn-primary { - width: 100%; - max-width: 600px; - margin: 10px 0; - border-radius: 5px; - height: 50px; - padding: 5px; -} - -form#contact textarea { - height: 150px; -} -form#contact input.btn.btn-primary { - max-width: 150px; -} - -.center { - text-align: center; - -} -@media (max-width: 1200px) { - body { - font-size: 20px; - } - #main { - background-image: none; - } - #why { - background-image: none; - } - - #how { - background-image: none; - } - - #where { - background-image: none; - } - #fixedbtn-offer { - display: none; - } - .event-box { - margin-left: 0; - margin-top: 40px; - } - .left svg { - margin-top: 10px; - } -} - -@media (max-width: 992px) { - body { - font-size: 15px; - } - p { - margin-bottom: 10px; - } - h1.main-title { - font-size: 3em !important; - } - div.left{ - display: none; - } - a#start { - display: none; - } - div#footer { - background-color: #fff; - color: $dark-color; - } - - img#logo { - width: 100px; - } - #main, #why, #contact { - padding-top: 30px; - } - - .event-info h3 { - margin-bottom: 0px; - font-size: 1.3em; - } - .event-info { - margin-left: 0; - } - .event-box { - padding-top: 0px; - margin-top: 20px; - } - .btn-primary { - font-size: 1.0em; - } - #fixedbtn-up, #fixedbtn-reg, #fixedbtn-twitter, #fixedbtn-facebook, #fixedbtn-instagram, #fixedbtn-slack, #fixedbtn-github { - display: none; - } - .nav-bottom { - display: none; - font-size: 1.5em; - } - .sponsors img { - max-width: 200px; - } - .support img { - max-width: 120px; - } - .support { - text-align: cen center; - } - .sponsors { - text-align: center; - } -} diff --git a/docs/scss/style.scss b/docs/scss/style.scss deleted file mode 100644 index 856d710..0000000 --- a/docs/scss/style.scss +++ /dev/null @@ -1,45 +0,0 @@ -@import url('https://fonts.googleapis.com/css?family=Heebo:100,200,400,600,900'); -@import 'variables.scss'; - -body, .event-box { - font-family: 'Heebo', sans-serif; -} -.navbar { - font-family: 'Heebo', sans-serif; - font-weight: 400; -} -h1.big-title { - font-family: 'Heebo', sans-serif; - font-weight: 900; - font-size: 3em; -} -h1.main-title { - font-size: 4em; -} - -p.event a { - color: $light-color; -} - -p.event { - font-size: 1em; -} - -p.resource { - color: $dark-color -} - -.btn-primary { - margin: 5px; - - width: 300px; - font-size: 1.5em; -} - -.btn-primary:hover { - background-color: $highlight-hover -} - -a.btn-primary { - text-decoration: none; -} diff --git a/docs/test.html b/docs/test.html deleted file mode 100644 index 5944e67..0000000 --- a/docs/test.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - Bootply snippet - Bootstrap Navbar Static top Template - - - - - - - - - - - - - - -
-
-

Bootstrap starter template

-

Use this document as a way to quickly start any new project.
All you get is this text and a mostly barebones HTML document.

-
-
- - - - - - - \ No newline at end of file diff --git a/docs/today.html b/docs/today.html deleted file mode 100644 index af46992..0000000 --- a/docs/today.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - Bootply snippet - Bootstrap Grid - - - - - - - - - - - - - - -
-
-
-

Dec

-
-

Nov

-
-
-
-

24 April 2018

-
-

13:01

-

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ullamcorper egestas ullamcorper. Aenean facilisis varius augue, sed consequat neque fringilla ut. Cras at est eu lectus pulvinar dapibus eu quis dolor. Vivamus mattis odio et enim malesuada luctus. Pellentesque libero quam, porta vel porta id, vulputate in sem. Ut consequat bibendum leo, quis condimentum arcu lobortis in. Proin metus leo, porta vel ipsum imperdiet, elementum pharetra sapien. Phasellus dapibus commodo semper.

-
-
-

13:15

-

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ullamcorper egestas ullamcorper.

-
-
-
-

Task name

-
-

Task name

-
-
-
- - - - - - \ No newline at end of file diff --git a/docs/what.html b/docs/what.html deleted file mode 100644 index 74ce082..0000000 --- a/docs/what.html +++ /dev/null @@ -1,147 +0,0 @@ - -
-
-

-- What?

-

Here's our amazing programme.

-
Fri 12
-
Sat 13
-
Sun 14

Where is the thesis retreat? -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TimeDescription
1700Reception and registration
1800Induction
1900Dinner
2030Careful Planning
2100Relaxing, socialising, rest
2200Supper snacks
2230Night owl writing session
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TimeDescription
0600Early bird writing session
0800A good hearty breakfast
0900The sorting hat
0930Write, write, write*
1100Snack stop.
1130Write, write, write*
1300Champions Lunch
1400Relax, nap, chill*
1430Write, write, write*
1600Reflection and peer proofing*
1730Free your mind
1830Dinner of Winners
1930Digest, discuss, plan
2030Write, write, write*
2200Supper snacks
2230Night owl writing session
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TimeDescription
0600Early bird writing session
0800Veterans breakfast
0900Write, write, write*
1130Snack stop
1200Presentation of Awards
1230Good luck buffet

-

*No phones allowed

-
-
\ No newline at end of file diff --git a/docs/where.html b/docs/where.html deleted file mode 100644 index 7ba235b..0000000 --- a/docs/where.html +++ /dev/null @@ -1,34 +0,0 @@ - -
-
-

-- Where?

-

Lane End Conference Centre

-

See it on the map.

-

A beautiful, accessible, quiet retreat. The perfect spot for you and your thesis. register now.

-
- -
-
-
\ No newline at end of file diff --git a/docs/why.html b/docs/why.html deleted file mode 100644 index 997ce77..0000000 --- a/docs/why.html +++ /dev/null @@ -1,20 +0,0 @@ - - \ No newline at end of file diff --git a/Using Python, and your environment.ipynb b/misc:old/Using Python, and your environment.ipynb similarity index 100% rename from Using Python, and your environment.ipynb rename to misc:old/Using Python, and your environment.ipynb diff --git a/data-structures.py b/misc:old/data-structures.py similarity index 100% rename from data-structures.py rename to misc:old/data-structures.py diff --git a/data-structures1.py b/misc:old/data-structures1.py similarity index 100% rename from data-structures1.py rename to misc:old/data-structures1.py diff --git a/fizzbuzz.aux b/misc:old/fizzbuzz.aux similarity index 100% rename from fizzbuzz.aux rename to misc:old/fizzbuzz.aux diff --git a/fizzbuzz.log b/misc:old/fizzbuzz.log similarity index 100% rename from fizzbuzz.log rename to misc:old/fizzbuzz.log diff --git a/fizzbuzz.pdf b/misc:old/fizzbuzz.pdf similarity index 100% rename from fizzbuzz.pdf rename to misc:old/fizzbuzz.pdf diff --git a/fizzbuzz.py b/misc:old/fizzbuzz.py similarity index 100% rename from fizzbuzz.py rename to misc:old/fizzbuzz.py diff --git a/fizzbuzz.synctex.gz b/misc:old/fizzbuzz.synctex.gz similarity index 100% rename from fizzbuzz.synctex.gz rename to misc:old/fizzbuzz.synctex.gz diff --git a/fizzbuzz.tex b/misc:old/fizzbuzz.tex similarity index 100% rename from fizzbuzz.tex rename to misc:old/fizzbuzz.tex diff --git a/fizzcopy b/misc:old/fizzcopy similarity index 100% rename from fizzcopy rename to misc:old/fizzcopy diff --git a/header.png b/misc:old/header.png similarity index 100% rename from header.png rename to misc:old/header.png diff --git a/polynomial.py b/misc:old/polynomial.py similarity index 100% rename from polynomial.py rename to misc:old/polynomial.py diff --git a/pwd.py b/misc:old/pwd.py similarity index 100% rename from pwd.py rename to misc:old/pwd.py diff --git a/strings.py b/misc:old/strings.py similarity index 100% rename from strings.py rename to misc:old/strings.py diff --git a/table.py b/misc:old/table.py similarity index 100% rename from table.py rename to misc:old/table.py diff --git a/test.py b/misc:old/test.py similarity index 100% rename from test.py rename to misc:old/test.py diff --git a/my-folder/hello.py b/my-folder/hello.py deleted file mode 100644 index f1a1813..0000000 --- a/my-folder/hello.py +++ /dev/null @@ -1 +0,0 @@ -print("Hello world!") diff --git a/my-folder/hipynotes/command-line.txt b/my-folder/hipynotes/command-line.txt deleted file mode 100644 index a3f93ef..0000000 --- a/my-folder/hipynotes/command-line.txt +++ /dev/null @@ -1,7 +0,0 @@ -pwd -- prints the current directory (print working directory) -mkdir -- create a new directory e.g mkdir my-directory -ls -- view the contents of the current directory -cd -- change the current directory e.g cd my-directory (note cd .. goes to the directory "above") -rm -- remove a file e.g rm my-file, (note to remove a directory use rm -r) -python -- run python! -nano -- a text editor for the command line diff --git a/resources/python/basics/.DS_Store b/resources/python/basics/.DS_Store new file mode 100644 index 0000000..aeeb873 Binary files /dev/null and b/resources/python/basics/.DS_Store differ diff --git a/[BASICS] Getting Started With Python 1 - The Basics/Getting Started In Python 1 - The Basics.ipynb b/resources/python/basics/[BASICS] Getting Started With Python 1 - The Basics/Getting Started In Python 1 - The Basics.ipynb similarity index 100% rename from [BASICS] Getting Started With Python 1 - The Basics/Getting Started In Python 1 - The Basics.ipynb rename to resources/python/basics/[BASICS] Getting Started With Python 1 - The Basics/Getting Started In Python 1 - The Basics.ipynb diff --git a/[BASICS] Getting Started With Python 1 - The Basics/banner.png b/resources/python/basics/[BASICS] Getting Started With Python 1 - The Basics/banner.png similarity index 100% rename from [BASICS] Getting Started With Python 1 - The Basics/banner.png rename to resources/python/basics/[BASICS] Getting Started With Python 1 - The Basics/banner.png diff --git a/[BASICS] Getting Started With Python 2 - The Basics/Getting Started With Python 2 - The Basics.ipynb b/resources/python/basics/[BASICS] Getting Started With Python 2 - The Basics/Getting Started With Python 2 - The Basics.ipynb similarity index 100% rename from [BASICS] Getting Started With Python 2 - The Basics/Getting Started With Python 2 - The Basics.ipynb rename to resources/python/basics/[BASICS] Getting Started With Python 2 - The Basics/Getting Started With Python 2 - The Basics.ipynb diff --git a/[BASICS] Getting Started With Python 2 - The Basics/header.png b/resources/python/basics/[BASICS] Getting Started With Python 2 - The Basics/header.png similarity index 100% rename from [BASICS] Getting Started With Python 2 - The Basics/header.png rename to resources/python/basics/[BASICS] Getting Started With Python 2 - The Basics/header.png diff --git a/[BASICS] Numpy and Pandas/Numpy and Pandas.ipynb b/resources/python/basics/[BASICS] Numpy and Pandas/Numpy and Pandas.ipynb similarity index 100% rename from [BASICS] Numpy and Pandas/Numpy and Pandas.ipynb rename to resources/python/basics/[BASICS] Numpy and Pandas/Numpy and Pandas.ipynb diff --git a/[BASICS] Numpy and Pandas/header.png b/resources/python/basics/[BASICS] Numpy and Pandas/header.png similarity index 100% rename from [BASICS] Numpy and Pandas/header.png rename to resources/python/basics/[BASICS] Numpy and Pandas/header.png diff --git a/[ML] Decision Trees/Decision Trees.ipynb b/resources/python/machine learning/[ML] Decision Trees/Decision Trees.ipynb similarity index 100% rename from [ML] Decision Trees/Decision Trees.ipynb rename to resources/python/machine learning/[ML] Decision Trees/Decision Trees.ipynb diff --git a/[ML] Decision Trees/header.png b/resources/python/machine learning/[ML] Decision Trees/header.png similarity index 100% rename from [ML] Decision Trees/header.png rename to resources/python/machine learning/[ML] Decision Trees/header.png diff --git a/[ML] Decision Trees/test.csv b/resources/python/machine learning/[ML] Decision Trees/test.csv similarity index 100% rename from [ML] Decision Trees/test.csv rename to resources/python/machine learning/[ML] Decision Trees/test.csv diff --git a/[ML] Introduction to Machine Learning/Introduction to Machine Learning.ipynb b/resources/python/machine learning/[ML] Introduction to Machine Learning/Introduction to Machine Learning.ipynb similarity index 100% rename from [ML] Introduction to Machine Learning/Introduction to Machine Learning.ipynb rename to resources/python/machine learning/[ML] Introduction to Machine Learning/Introduction to Machine Learning.ipynb diff --git a/[ML] Introduction to Machine Learning/header.png b/resources/python/machine learning/[ML] Introduction to Machine Learning/header.png similarity index 100% rename from [ML] Introduction to Machine Learning/header.png rename to resources/python/machine learning/[ML] Introduction to Machine Learning/header.png diff --git a/[ML] K Means Clustering/CUSTOMER_DATA.csv b/resources/python/machine learning/[ML] K Means Clustering/CUSTOMER_DATA.csv similarity index 100% rename from [ML] K Means Clustering/CUSTOMER_DATA.csv rename to resources/python/machine learning/[ML] K Means Clustering/CUSTOMER_DATA.csv diff --git a/[ML] K Means Clustering/K Means Clustering.ipynb b/resources/python/machine learning/[ML] K Means Clustering/K Means Clustering.ipynb similarity index 100% rename from [ML] K Means Clustering/K Means Clustering.ipynb rename to resources/python/machine learning/[ML] K Means Clustering/K Means Clustering.ipynb diff --git a/[ML] K Means Clustering/header.png b/resources/python/machine learning/[ML] K Means Clustering/header.png similarity index 100% rename from [ML] K Means Clustering/header.png rename to resources/python/machine learning/[ML] K Means Clustering/header.png diff --git a/[ML] K Nearest Neighbours/K Nearest Neighbours.ipynb b/resources/python/machine learning/[ML] K Nearest Neighbours/K Nearest Neighbours.ipynb similarity index 100% rename from [ML] K Nearest Neighbours/K Nearest Neighbours.ipynb rename to resources/python/machine learning/[ML] K Nearest Neighbours/K Nearest Neighbours.ipynb diff --git a/[ML] K Nearest Neighbours/header.png b/resources/python/machine learning/[ML] K Nearest Neighbours/header.png similarity index 100% rename from [ML] K Nearest Neighbours/header.png rename to resources/python/machine learning/[ML] K Nearest Neighbours/header.png diff --git a/[ML] K Nearest Neighbours/project_training.csv b/resources/python/machine learning/[ML] K Nearest Neighbours/project_training.csv similarity index 100% rename from [ML] K Nearest Neighbours/project_training.csv rename to resources/python/machine learning/[ML] K Nearest Neighbours/project_training.csv diff --git a/[ML] K Nearest Neighbours/test_data.csv b/resources/python/machine learning/[ML] K Nearest Neighbours/test_data.csv similarity index 100% rename from [ML] K Nearest Neighbours/test_data.csv rename to resources/python/machine learning/[ML] K Nearest Neighbours/test_data.csv diff --git a/[ML] Support Vector Machines/Support Vector Machines.ipynb b/resources/python/machine learning/[ML] Support Vector Machines/Support Vector Machines.ipynb similarity index 100% rename from [ML] Support Vector Machines/Support Vector Machines.ipynb rename to resources/python/machine learning/[ML] Support Vector Machines/Support Vector Machines.ipynb diff --git a/[ML] Support Vector Machines/example.csv b/resources/python/machine learning/[ML] Support Vector Machines/example.csv similarity index 100% rename from [ML] Support Vector Machines/example.csv rename to resources/python/machine learning/[ML] Support Vector Machines/example.csv diff --git a/[ML] Support Vector Machines/header.png b/resources/python/machine learning/[ML] Support Vector Machines/header.png similarity index 100% rename from [ML] Support Vector Machines/header.png rename to resources/python/machine learning/[ML] Support Vector Machines/header.png diff --git a/[ML] Support Vector Machines/svn.png b/resources/python/machine learning/[ML] Support Vector Machines/svn.png similarity index 100% rename from [ML] Support Vector Machines/svn.png rename to resources/python/machine learning/[ML] Support Vector Machines/svn.png diff --git a/PurePy 0. Woffle and Getting Started/0.1 Introduction.ipynb b/resources/python/pure/PurePy 0. Woffle and Getting Started/0.1 Introduction.ipynb similarity index 100% rename from PurePy 0. Woffle and Getting Started/0.1 Introduction.ipynb rename to resources/python/pure/PurePy 0. Woffle and Getting Started/0.1 Introduction.ipynb diff --git a/PurePy 0. Woffle and Getting Started/Selection_117.png b/resources/python/pure/PurePy 0. Woffle and Getting Started/Selection_117.png similarity index 100% rename from PurePy 0. Woffle and Getting Started/Selection_117.png rename to resources/python/pure/PurePy 0. Woffle and Getting Started/Selection_117.png diff --git a/PurePy 0. Woffle and Getting Started/SpyderPython 3.6_112.png b/resources/python/pure/PurePy 0. Woffle and Getting Started/SpyderPython 3.6_112.png similarity index 100% rename from PurePy 0. Woffle and Getting Started/SpyderPython 3.6_112.png rename to resources/python/pure/PurePy 0. Woffle and Getting Started/SpyderPython 3.6_112.png diff --git a/PurePy 0. Woffle and Getting Started/atom-python.png b/resources/python/pure/PurePy 0. Woffle and Getting Started/atom-python.png similarity index 100% rename from PurePy 0. Woffle and Getting Started/atom-python.png rename to resources/python/pure/PurePy 0. Woffle and Getting Started/atom-python.png diff --git a/PurePy 0. Woffle and Getting Started/header1.png b/resources/python/pure/PurePy 0. Woffle and Getting Started/header1.png similarity index 100% rename from PurePy 0. Woffle and Getting Started/header1.png rename to resources/python/pure/PurePy 0. Woffle and Getting Started/header1.png diff --git a/PurePy 1. Numbers and Variables/Numbers and variables.ipynb b/resources/python/pure/PurePy 1. Numbers and Variables/Numbers and variables.ipynb similarity index 100% rename from PurePy 1. Numbers and Variables/Numbers and variables.ipynb rename to resources/python/pure/PurePy 1. Numbers and Variables/Numbers and variables.ipynb diff --git a/PurePy 1. Numbers and Variables/header.png b/resources/python/pure/PurePy 1. Numbers and Variables/header.png similarity index 100% rename from PurePy 1. Numbers and Variables/header.png rename to resources/python/pure/PurePy 1. Numbers and Variables/header.png diff --git a/PurePy 10. Object-Oriented Programming/10.1 Classes and objects.ipynb b/resources/python/pure/PurePy 10. Object-Oriented Programming/10.1 Classes and objects.ipynb similarity index 100% rename from PurePy 10. Object-Oriented Programming/10.1 Classes and objects.ipynb rename to resources/python/pure/PurePy 10. Object-Oriented Programming/10.1 Classes and objects.ipynb diff --git a/PurePy 10. Object-Oriented Programming/10.2 Inheritance, Composition, and Magic Methods.ipynb b/resources/python/pure/PurePy 10. Object-Oriented Programming/10.2 Inheritance, Composition, and Magic Methods.ipynb similarity index 100% rename from PurePy 10. Object-Oriented Programming/10.2 Inheritance, Composition, and Magic Methods.ipynb rename to resources/python/pure/PurePy 10. Object-Oriented Programming/10.2 Inheritance, Composition, and Magic Methods.ipynb diff --git a/PurePy 10. Object-Oriented Programming/header10.1.png b/resources/python/pure/PurePy 10. Object-Oriented Programming/header10.1.png similarity index 100% rename from PurePy 10. Object-Oriented Programming/header10.1.png rename to resources/python/pure/PurePy 10. Object-Oriented Programming/header10.1.png diff --git a/PurePy 10. Object-Oriented Programming/header10.2.png b/resources/python/pure/PurePy 10. Object-Oriented Programming/header10.2.png similarity index 100% rename from PurePy 10. Object-Oriented Programming/header10.2.png rename to resources/python/pure/PurePy 10. Object-Oriented Programming/header10.2.png diff --git a/PurePy 10.5. Object-Oriented Programming./ipynb_checkpoints/Introduction-To-Object-Oriented-Programming-In-Python-(Part-I)-checkpoint.ipynb b/resources/python/pure/PurePy 10.5. Object-Oriented Programming./ipynb_checkpoints/Introduction-To-Object-Oriented-Programming-In-Python-(Part-I)-checkpoint.ipynb similarity index 100% rename from PurePy 10.5. Object-Oriented Programming./ipynb_checkpoints/Introduction-To-Object-Oriented-Programming-In-Python-(Part-I)-checkpoint.ipynb rename to resources/python/pure/PurePy 10.5. Object-Oriented Programming./ipynb_checkpoints/Introduction-To-Object-Oriented-Programming-In-Python-(Part-I)-checkpoint.ipynb diff --git a/PurePy 10.5. Object-Oriented Programming/ipynb_checkpoints/Introduction-To-Object-Oriented-Programming-In-Python-(Part-I)-checkpoint.ipynb b/resources/python/pure/PurePy 10.5. Object-Oriented Programming/ipynb_checkpoints/Introduction-To-Object-Oriented-Programming-In-Python-(Part-I)-checkpoint.ipynb similarity index 100% rename from PurePy 10.5. Object-Oriented Programming/ipynb_checkpoints/Introduction-To-Object-Oriented-Programming-In-Python-(Part-I)-checkpoint.ipynb rename to resources/python/pure/PurePy 10.5. Object-Oriented Programming/ipynb_checkpoints/Introduction-To-Object-Oriented-Programming-In-Python-(Part-I)-checkpoint.ipynb diff --git a/PurePy 11. Exceptions/Exceptions, and debugging.ipynb b/resources/python/pure/PurePy 11. Exceptions/Exceptions, and debugging.ipynb similarity index 100% rename from PurePy 11. Exceptions/Exceptions, and debugging.ipynb rename to resources/python/pure/PurePy 11. Exceptions/Exceptions, and debugging.ipynb diff --git a/PurePy 11. Exceptions/header.png b/resources/python/pure/PurePy 11. Exceptions/header.png similarity index 100% rename from PurePy 11. Exceptions/header.png rename to resources/python/pure/PurePy 11. Exceptions/header.png diff --git a/PurePy 11. Exceptions/header2.png b/resources/python/pure/PurePy 11. Exceptions/header2.png similarity index 100% rename from PurePy 11. Exceptions/header2.png rename to resources/python/pure/PurePy 11. Exceptions/header2.png diff --git a/PurePy 12. Parallel Computing/12.0 Parallel Computing.ipynb b/resources/python/pure/PurePy 12. Parallel Computing/12.0 Parallel Computing.ipynb similarity index 100% rename from PurePy 12. Parallel Computing/12.0 Parallel Computing.ipynb rename to resources/python/pure/PurePy 12. Parallel Computing/12.0 Parallel Computing.ipynb diff --git a/PurePy 12. Parallel Computing/header.png b/resources/python/pure/PurePy 12. Parallel Computing/header.png similarity index 100% rename from PurePy 12. Parallel Computing/header.png rename to resources/python/pure/PurePy 12. Parallel Computing/header.png diff --git a/PurePy 12. Parallel Computing/pipe.py b/resources/python/pure/PurePy 12. Parallel Computing/pipe.py similarity index 100% rename from PurePy 12. Parallel Computing/pipe.py rename to resources/python/pure/PurePy 12. Parallel Computing/pipe.py diff --git a/PurePy 12. Parallel Computing/test.py b/resources/python/pure/PurePy 12. Parallel Computing/test.py similarity index 100% rename from PurePy 12. Parallel Computing/test.py rename to resources/python/pure/PurePy 12. Parallel Computing/test.py diff --git a/PurePy 12. Parallel Computing/test2.py b/resources/python/pure/PurePy 12. Parallel Computing/test2.py similarity index 100% rename from PurePy 12. Parallel Computing/test2.py rename to resources/python/pure/PurePy 12. Parallel Computing/test2.py diff --git a/PurePy 12. Parallel Computing/test3.py b/resources/python/pure/PurePy 12. Parallel Computing/test3.py similarity index 100% rename from PurePy 12. Parallel Computing/test3.py rename to resources/python/pure/PurePy 12. Parallel Computing/test3.py diff --git a/PurePy 12. Parallel Computing/test4.py b/resources/python/pure/PurePy 12. Parallel Computing/test4.py similarity index 100% rename from PurePy 12. Parallel Computing/test4.py rename to resources/python/pure/PurePy 12. Parallel Computing/test4.py diff --git a/PurePy 2. Logic and Flow/2.0 Logic and Flow.ipynb b/resources/python/pure/PurePy 2. Logic and Flow/2.0 Logic and Flow.ipynb similarity index 100% rename from PurePy 2. Logic and Flow/2.0 Logic and Flow.ipynb rename to resources/python/pure/PurePy 2. Logic and Flow/2.0 Logic and Flow.ipynb diff --git a/PurePy 2. Logic and Flow/header.png b/resources/python/pure/PurePy 2. Logic and Flow/header.png similarity index 100% rename from PurePy 2. Logic and Flow/header.png rename to resources/python/pure/PurePy 2. Logic and Flow/header.png diff --git a/PurePy 3. Importing modules/Importing more functions.ipynb b/resources/python/pure/PurePy 3. Importing modules/Importing more functions.ipynb similarity index 100% rename from PurePy 3. Importing modules/Importing more functions.ipynb rename to resources/python/pure/PurePy 3. Importing modules/Importing more functions.ipynb diff --git a/PurePy 3. Importing modules/__pycache__/constants.cpython-36.pyc b/resources/python/pure/PurePy 3. Importing modules/__pycache__/constants.cpython-36.pyc similarity index 100% rename from PurePy 3. Importing modules/__pycache__/constants.cpython-36.pyc rename to resources/python/pure/PurePy 3. Importing modules/__pycache__/constants.cpython-36.pyc diff --git a/PurePy 3. Importing modules/constants.py b/resources/python/pure/PurePy 3. Importing modules/constants.py similarity index 100% rename from PurePy 3. Importing modules/constants.py rename to resources/python/pure/PurePy 3. Importing modules/constants.py diff --git a/PurePy 3. Importing modules/header.png b/resources/python/pure/PurePy 3. Importing modules/header.png similarity index 100% rename from PurePy 3. Importing modules/header.png rename to resources/python/pure/PurePy 3. Importing modules/header.png diff --git a/PurePy 4. Defining Our Own Functions/Defining our own functions.ipynb b/resources/python/pure/PurePy 4. Defining Our Own Functions/Defining our own functions.ipynb similarity index 100% rename from PurePy 4. Defining Our Own Functions/Defining our own functions.ipynb rename to resources/python/pure/PurePy 4. Defining Our Own Functions/Defining our own functions.ipynb diff --git a/PurePy 4. Defining Our Own Functions/__pycache__/example.cpython-36.pyc b/resources/python/pure/PurePy 4. Defining Our Own Functions/__pycache__/example.cpython-36.pyc similarity index 100% rename from PurePy 4. Defining Our Own Functions/__pycache__/example.cpython-36.pyc rename to resources/python/pure/PurePy 4. Defining Our Own Functions/__pycache__/example.cpython-36.pyc diff --git a/PurePy 4. Defining Our Own Functions/__pycache__/geometry.cpython-36.pyc b/resources/python/pure/PurePy 4. Defining Our Own Functions/__pycache__/geometry.cpython-36.pyc similarity index 100% rename from PurePy 4. Defining Our Own Functions/__pycache__/geometry.cpython-36.pyc rename to resources/python/pure/PurePy 4. Defining Our Own Functions/__pycache__/geometry.cpython-36.pyc diff --git a/PurePy 4. Defining Our Own Functions/effects.py b/resources/python/pure/PurePy 4. Defining Our Own Functions/effects.py similarity index 100% rename from PurePy 4. Defining Our Own Functions/effects.py rename to resources/python/pure/PurePy 4. Defining Our Own Functions/effects.py diff --git a/PurePy 4. Defining Our Own Functions/example.py b/resources/python/pure/PurePy 4. Defining Our Own Functions/example.py similarity index 100% rename from PurePy 4. Defining Our Own Functions/example.py rename to resources/python/pure/PurePy 4. Defining Our Own Functions/example.py diff --git a/PurePy 4. Defining Our Own Functions/geometry.py b/resources/python/pure/PurePy 4. Defining Our Own Functions/geometry.py similarity index 100% rename from PurePy 4. Defining Our Own Functions/geometry.py rename to resources/python/pure/PurePy 4. Defining Our Own Functions/geometry.py diff --git a/PurePy 4. Defining Our Own Functions/geometry_demo.py b/resources/python/pure/PurePy 4. Defining Our Own Functions/geometry_demo.py similarity index 100% rename from PurePy 4. Defining Our Own Functions/geometry_demo.py rename to resources/python/pure/PurePy 4. Defining Our Own Functions/geometry_demo.py diff --git a/PurePy 4. Defining Our Own Functions/guitarmon.wav b/resources/python/pure/PurePy 4. Defining Our Own Functions/guitarmon.wav similarity index 100% rename from PurePy 4. Defining Our Own Functions/guitarmon.wav rename to resources/python/pure/PurePy 4. Defining Our Own Functions/guitarmon.wav diff --git a/PurePy 4. Defining Our Own Functions/header.png b/resources/python/pure/PurePy 4. Defining Our Own Functions/header.png similarity index 100% rename from PurePy 4. Defining Our Own Functions/header.png rename to resources/python/pure/PurePy 4. Defining Our Own Functions/header.png diff --git a/PurePy 4. Defining Our Own Functions/reverseguitar.wav b/resources/python/pure/PurePy 4. Defining Our Own Functions/reverseguitar.wav similarity index 100% rename from PurePy 4. Defining Our Own Functions/reverseguitar.wav rename to resources/python/pure/PurePy 4. Defining Our Own Functions/reverseguitar.wav diff --git a/PurePy 5. Data Structures/5.0 Data Structures.ipynb b/resources/python/pure/PurePy 5. Data Structures/5.0 Data Structures.ipynb similarity index 100% rename from PurePy 5. Data Structures/5.0 Data Structures.ipynb rename to resources/python/pure/PurePy 5. Data Structures/5.0 Data Structures.ipynb diff --git a/PurePy 5. Data Structures/Directory.txt b/resources/python/pure/PurePy 5. Data Structures/Directory.txt similarity index 100% rename from PurePy 5. Data Structures/Directory.txt rename to resources/python/pure/PurePy 5. Data Structures/Directory.txt diff --git a/PurePy 5. Data Structures/header.png b/resources/python/pure/PurePy 5. Data Structures/header.png similarity index 100% rename from PurePy 5. Data Structures/header.png rename to resources/python/pure/PurePy 5. Data Structures/header.png diff --git a/PurePy 5.5 Command-line interlude/5.5 The command line.ipynb b/resources/python/pure/PurePy 5.5 Command-line interlude/5.5 The command line.ipynb similarity index 100% rename from PurePy 5.5 Command-line interlude/5.5 The command line.ipynb rename to resources/python/pure/PurePy 5.5 Command-line interlude/5.5 The command line.ipynb diff --git a/PurePy 5.5 Command-line interlude/Selection_113.png b/resources/python/pure/PurePy 5.5 Command-line interlude/Selection_113.png similarity index 100% rename from PurePy 5.5 Command-line interlude/Selection_113.png rename to resources/python/pure/PurePy 5.5 Command-line interlude/Selection_113.png diff --git a/PurePy 5.5 Command-line interlude/header0.2.png b/resources/python/pure/PurePy 5.5 Command-line interlude/header0.2.png similarity index 100% rename from PurePy 5.5 Command-line interlude/header0.2.png rename to resources/python/pure/PurePy 5.5 Command-line interlude/header0.2.png diff --git a/PurePy 6. Strings and Text/6.0 Working with text.ipynb b/resources/python/pure/PurePy 6. Strings and Text/6.0 Working with text.ipynb similarity index 100% rename from PurePy 6. Strings and Text/6.0 Working with text.ipynb rename to resources/python/pure/PurePy 6. Strings and Text/6.0 Working with text.ipynb diff --git a/PurePy 6. Strings and Text/6.1 Regular Expressions.ipynb b/resources/python/pure/PurePy 6. Strings and Text/6.1 Regular Expressions.ipynb similarity index 100% rename from PurePy 6. Strings and Text/6.1 Regular Expressions.ipynb rename to resources/python/pure/PurePy 6. Strings and Text/6.1 Regular Expressions.ipynb diff --git a/PurePy 6. Strings and Text/example.py b/resources/python/pure/PurePy 6. Strings and Text/example.py similarity index 100% rename from PurePy 6. Strings and Text/example.py rename to resources/python/pure/PurePy 6. Strings and Text/example.py diff --git a/PurePy 6. Strings and Text/header.png b/resources/python/pure/PurePy 6. Strings and Text/header.png similarity index 100% rename from PurePy 6. Strings and Text/header.png rename to resources/python/pure/PurePy 6. Strings and Text/header.png diff --git a/PurePy 6. Strings and Text/obituary b/resources/python/pure/PurePy 6. Strings and Text/obituary similarity index 100% rename from PurePy 6. Strings and Text/obituary rename to resources/python/pure/PurePy 6. Strings and Text/obituary diff --git a/PurePy 6. Strings and Text/obituary.txt b/resources/python/pure/PurePy 6. Strings and Text/obituary.txt similarity index 100% rename from PurePy 6. Strings and Text/obituary.txt rename to resources/python/pure/PurePy 6. Strings and Text/obituary.txt diff --git a/PurePy 7. Importing Data/7.1 Opening Files.ipynb b/resources/python/pure/PurePy 7. Importing Data/7.1 Opening Files.ipynb similarity index 100% rename from PurePy 7. Importing Data/7.1 Opening Files.ipynb rename to resources/python/pure/PurePy 7. Importing Data/7.1 Opening Files.ipynb diff --git a/PurePy 7. Importing Data/7.2 Reading and storing data; CSV, JSON, and more.ipynb b/resources/python/pure/PurePy 7. Importing Data/7.2 Reading and storing data; CSV, JSON, and more.ipynb similarity index 100% rename from PurePy 7. Importing Data/7.2 Reading and storing data; CSV, JSON, and more.ipynb rename to resources/python/pure/PurePy 7. Importing Data/7.2 Reading and storing data; CSV, JSON, and more.ipynb diff --git a/PurePy 7. Importing Data/Musical_Instruments_5.json b/resources/python/pure/PurePy 7. Importing Data/Musical_Instruments_5.json similarity index 100% rename from PurePy 7. Importing Data/Musical_Instruments_5.json rename to resources/python/pure/PurePy 7. Importing Data/Musical_Instruments_5.json diff --git a/PurePy 7. Importing Data/book_review.json b/resources/python/pure/PurePy 7. Importing Data/book_review.json similarity index 100% rename from PurePy 7. Importing Data/book_review.json rename to resources/python/pure/PurePy 7. Importing Data/book_review.json diff --git a/PurePy 7. Importing Data/haiku.txt b/resources/python/pure/PurePy 7. Importing Data/haiku.txt similarity index 100% rename from PurePy 7. Importing Data/haiku.txt rename to resources/python/pure/PurePy 7. Importing Data/haiku.txt diff --git a/PurePy 7. Importing Data/header7.1.png b/resources/python/pure/PurePy 7. Importing Data/header7.1.png similarity index 100% rename from PurePy 7. Importing Data/header7.1.png rename to resources/python/pure/PurePy 7. Importing Data/header7.1.png diff --git a/PurePy 7. Importing Data/header7.2.png b/resources/python/pure/PurePy 7. Importing Data/header7.2.png similarity index 100% rename from PurePy 7. Importing Data/header7.2.png rename to resources/python/pure/PurePy 7. Importing Data/header7.2.png diff --git a/PurePy 7. Importing Data/movies-new.csv b/resources/python/pure/PurePy 7. Importing Data/movies-new.csv similarity index 100% rename from PurePy 7. Importing Data/movies-new.csv rename to resources/python/pure/PurePy 7. Importing Data/movies-new.csv diff --git a/PurePy 7. Importing Data/my_customers.json b/resources/python/pure/PurePy 7. Importing Data/my_customers.json similarity index 100% rename from PurePy 7. Importing Data/my_customers.json rename to resources/python/pure/PurePy 7. Importing Data/my_customers.json diff --git a/PurePy 7. Importing Data/newhaiku.txt b/resources/python/pure/PurePy 7. Importing Data/newhaiku.txt similarity index 100% rename from PurePy 7. Importing Data/newhaiku.txt rename to resources/python/pure/PurePy 7. Importing Data/newhaiku.txt diff --git a/PurePy 7. Importing Data/topmovies.csv b/resources/python/pure/PurePy 7. Importing Data/topmovies.csv similarity index 100% rename from PurePy 7. Importing Data/topmovies.csv rename to resources/python/pure/PurePy 7. Importing Data/topmovies.csv diff --git a/PurePy 8. Advanced Flow Control/8.0 Advanced Flow Control.ipynb b/resources/python/pure/PurePy 8. Advanced Flow Control/8.0 Advanced Flow Control.ipynb similarity index 100% rename from PurePy 8. Advanced Flow Control/8.0 Advanced Flow Control.ipynb rename to resources/python/pure/PurePy 8. Advanced Flow Control/8.0 Advanced Flow Control.ipynb diff --git a/PurePy 8. Advanced Flow Control/Copy of header.png b/resources/python/pure/PurePy 8. Advanced Flow Control/Copy of header.png similarity index 100% rename from PurePy 8. Advanced Flow Control/Copy of header.png rename to resources/python/pure/PurePy 8. Advanced Flow Control/Copy of header.png diff --git a/PurePy 9. Advanced Functions/9.0 Advanced Functions and Functional Programming.ipynb b/resources/python/pure/PurePy 9. Advanced Functions/9.0 Advanced Functions and Functional Programming.ipynb similarity index 100% rename from PurePy 9. Advanced Functions/9.0 Advanced Functions and Functional Programming.ipynb rename to resources/python/pure/PurePy 9. Advanced Functions/9.0 Advanced Functions and Functional Programming.ipynb diff --git a/PurePy 9. Advanced Functions/fastaparse.py b/resources/python/pure/PurePy 9. Advanced Functions/fastaparse.py similarity index 100% rename from PurePy 9. Advanced Functions/fastaparse.py rename to resources/python/pure/PurePy 9. Advanced Functions/fastaparse.py diff --git a/PurePy 9. Advanced Functions/genes-short.fasta b/resources/python/pure/PurePy 9. Advanced Functions/genes-short.fasta similarity index 100% rename from PurePy 9. Advanced Functions/genes-short.fasta rename to resources/python/pure/PurePy 9. Advanced Functions/genes-short.fasta diff --git a/PurePy 9. Advanced Functions/header.png b/resources/python/pure/PurePy 9. Advanced Functions/header.png similarity index 100% rename from PurePy 9. Advanced Functions/header.png rename to resources/python/pure/PurePy 9. Advanced Functions/header.png diff --git a/PurePy 9. Advanced Functions/high.fasta b/resources/python/pure/PurePy 9. Advanced Functions/high.fasta similarity index 100% rename from PurePy 9. Advanced Functions/high.fasta rename to resources/python/pure/PurePy 9. Advanced Functions/high.fasta diff --git a/[SOURCING] Importing Data From Files/Excel_Sample.xlsx b/resources/python/sourcing/[SOURCING] Importing Data From Files/Excel_Sample.xlsx similarity index 100% rename from [SOURCING] Importing Data From Files/Excel_Sample.xlsx rename to resources/python/sourcing/[SOURCING] Importing Data From Files/Excel_Sample.xlsx diff --git a/[SOURCING] Importing Data From Files/Importing Files From Files.ipynb b/resources/python/sourcing/[SOURCING] Importing Data From Files/Importing Files From Files.ipynb similarity index 100% rename from [SOURCING] Importing Data From Files/Importing Files From Files.ipynb rename to resources/python/sourcing/[SOURCING] Importing Data From Files/Importing Files From Files.ipynb diff --git a/[SOURCING] Importing Data From Files/example.csv b/resources/python/sourcing/[SOURCING] Importing Data From Files/example.csv similarity index 100% rename from [SOURCING] Importing Data From Files/example.csv rename to resources/python/sourcing/[SOURCING] Importing Data From Files/example.csv diff --git a/[SOURCING] Importing Data From Files/header.png b/resources/python/sourcing/[SOURCING] Importing Data From Files/header.png similarity index 100% rename from [SOURCING] Importing Data From Files/header.png rename to resources/python/sourcing/[SOURCING] Importing Data From Files/header.png diff --git a/[SOURCING] Importing Data From The Web/Importing Data From The Web.ipynb b/resources/python/sourcing/[SOURCING] Importing Data From The Web/Importing Data From The Web.ipynb similarity index 100% rename from [SOURCING] Importing Data From The Web/Importing Data From The Web.ipynb rename to resources/python/sourcing/[SOURCING] Importing Data From The Web/Importing Data From The Web.ipynb diff --git a/[SOURCING] Importing Data From The Web/header.png b/resources/python/sourcing/[SOURCING] Importing Data From The Web/header.png similarity index 100% rename from [SOURCING] Importing Data From The Web/header.png rename to resources/python/sourcing/[SOURCING] Importing Data From The Web/header.png diff --git a/[STATISTICS] ANOVA (Analysis Of Variance)/ANOVA (Analysis Of Variance).ipynb b/resources/python/statistics/[STATISTICS] ANOVA (Analysis Of Variance)/ANOVA (Analysis Of Variance).ipynb similarity index 100% rename from [STATISTICS] ANOVA (Analysis Of Variance)/ANOVA (Analysis Of Variance).ipynb rename to resources/python/statistics/[STATISTICS] ANOVA (Analysis Of Variance)/ANOVA (Analysis Of Variance).ipynb diff --git a/[STATISTICS] ANOVA (Analysis Of Variance)/ToothGrowth.csv b/resources/python/statistics/[STATISTICS] ANOVA (Analysis Of Variance)/ToothGrowth.csv similarity index 100% rename from [STATISTICS] ANOVA (Analysis Of Variance)/ToothGrowth.csv rename to resources/python/statistics/[STATISTICS] ANOVA (Analysis Of Variance)/ToothGrowth.csv diff --git a/[STATISTICS] ANOVA (Analysis Of Variance)/angry_moods.csv b/resources/python/statistics/[STATISTICS] ANOVA (Analysis Of Variance)/angry_moods.csv similarity index 100% rename from [STATISTICS] ANOVA (Analysis Of Variance)/angry_moods.csv rename to resources/python/statistics/[STATISTICS] ANOVA (Analysis Of Variance)/angry_moods.csv diff --git a/[STATISTICS] ANOVA (Analysis Of Variance)/header.png b/resources/python/statistics/[STATISTICS] ANOVA (Analysis Of Variance)/header.png similarity index 100% rename from [STATISTICS] ANOVA (Analysis Of Variance)/header.png rename to resources/python/statistics/[STATISTICS] ANOVA (Analysis Of Variance)/header.png diff --git a/[STATISTICS] Hypothesis Testing In Python/Hypothesis Testing In Python.ipynb b/resources/python/statistics/[STATISTICS] Hypothesis Testing In Python/Hypothesis Testing In Python.ipynb similarity index 100% rename from [STATISTICS] Hypothesis Testing In Python/Hypothesis Testing In Python.ipynb rename to resources/python/statistics/[STATISTICS] Hypothesis Testing In Python/Hypothesis Testing In Python.ipynb diff --git a/[STATISTICS] Hypothesis Testing In Python/header.png b/resources/python/statistics/[STATISTICS] Hypothesis Testing In Python/header.png similarity index 100% rename from [STATISTICS] Hypothesis Testing In Python/header.png rename to resources/python/statistics/[STATISTICS] Hypothesis Testing In Python/header.png diff --git a/[STATISTICS] Introduction to Statistcal Analysis/Introduction to Statistical Analysis in Python.ipynb b/resources/python/statistics/[STATISTICS] Introduction to Statistcal Analysis/Introduction to Statistical Analysis in Python.ipynb similarity index 100% rename from [STATISTICS] Introduction to Statistcal Analysis/Introduction to Statistical Analysis in Python.ipynb rename to resources/python/statistics/[STATISTICS] Introduction to Statistcal Analysis/Introduction to Statistical Analysis in Python.ipynb diff --git a/[STATISTICS] Introduction to Statistcal Analysis/header.png b/resources/python/statistics/[STATISTICS] Introduction to Statistcal Analysis/header.png similarity index 100% rename from [STATISTICS] Introduction to Statistcal Analysis/header.png rename to resources/python/statistics/[STATISTICS] Introduction to Statistcal Analysis/header.png diff --git a/[STATISTICS] Statistical Regression/Statistical Regression.ipynb b/resources/python/statistics/[STATISTICS] Statistical Regression/Statistical Regression.ipynb similarity index 100% rename from [STATISTICS] Statistical Regression/Statistical Regression.ipynb rename to resources/python/statistics/[STATISTICS] Statistical Regression/Statistical Regression.ipynb diff --git a/[STATISTICS] Statistical Regression/header.png b/resources/python/statistics/[STATISTICS] Statistical Regression/header.png similarity index 100% rename from [STATISTICS] Statistical Regression/header.png rename to resources/python/statistics/[STATISTICS] Statistical Regression/header.png diff --git a/[STATISTICS] Statistical Regression/multiple.csv b/resources/python/statistics/[STATISTICS] Statistical Regression/multiple.csv similarity index 100% rename from [STATISTICS] Statistical Regression/multiple.csv rename to resources/python/statistics/[STATISTICS] Statistical Regression/multiple.csv diff --git a/[STATISTICS] Statistical Regression/project.csv b/resources/python/statistics/[STATISTICS] Statistical Regression/project.csv similarity index 100% rename from [STATISTICS] Statistical Regression/project.csv rename to resources/python/statistics/[STATISTICS] Statistical Regression/project.csv diff --git a/[STATISTICS] Statistical Regression/testData.csv b/resources/python/statistics/[STATISTICS] Statistical Regression/testData.csv similarity index 100% rename from [STATISTICS] Statistical Regression/testData.csv rename to resources/python/statistics/[STATISTICS] Statistical Regression/testData.csv diff --git a/[VISUALISATION] A Deeper Look Into Matplotlib/A Deeper Look Into Matplotlib.ipynb b/resources/python/visualisation/[VISUALISATION] A Deeper Look Into Matplotlib/A Deeper Look Into Matplotlib.ipynb similarity index 100% rename from [VISUALISATION] A Deeper Look Into Matplotlib/A Deeper Look Into Matplotlib.ipynb rename to resources/python/visualisation/[VISUALISATION] A Deeper Look Into Matplotlib/A Deeper Look Into Matplotlib.ipynb diff --git a/[VISUALISATION] A Deeper Look Into Matplotlib/header.png b/resources/python/visualisation/[VISUALISATION] A Deeper Look Into Matplotlib/header.png similarity index 100% rename from [VISUALISATION] A Deeper Look Into Matplotlib/header.png rename to resources/python/visualisation/[VISUALISATION] A Deeper Look Into Matplotlib/header.png diff --git a/[VISUALISATION] Interactive Plots With Bokeh/Bokeh.ipynb b/resources/python/visualisation/[VISUALISATION] Interactive Plots With Bokeh/Bokeh.ipynb similarity index 100% rename from [VISUALISATION] Interactive Plots With Bokeh/Bokeh.ipynb rename to resources/python/visualisation/[VISUALISATION] Interactive Plots With Bokeh/Bokeh.ipynb diff --git a/[VISUALISATION] Interactive Plots With Bokeh/header.png b/resources/python/visualisation/[VISUALISATION] Interactive Plots With Bokeh/header.png similarity index 100% rename from [VISUALISATION] Interactive Plots With Bokeh/header.png rename to resources/python/visualisation/[VISUALISATION] Interactive Plots With Bokeh/header.png diff --git a/[VISUALISATION] Panda's Built In Vis/Pandas Built In Vis.ipynb b/resources/python/visualisation/[VISUALISATION] Panda's Built In Vis/Pandas Built In Vis.ipynb similarity index 100% rename from [VISUALISATION] Panda's Built In Vis/Pandas Built In Vis.ipynb rename to resources/python/visualisation/[VISUALISATION] Panda's Built In Vis/Pandas Built In Vis.ipynb diff --git a/[VISUALISATION] Panda's Built In Vis/countries.xlsx b/resources/python/visualisation/[VISUALISATION] Panda's Built In Vis/countries.xlsx similarity index 100% rename from [VISUALISATION] Panda's Built In Vis/countries.xlsx rename to resources/python/visualisation/[VISUALISATION] Panda's Built In Vis/countries.xlsx diff --git a/[VISUALISATION] Panda's Built In Vis/data1.csv b/resources/python/visualisation/[VISUALISATION] Panda's Built In Vis/data1.csv similarity index 100% rename from [VISUALISATION] Panda's Built In Vis/data1.csv rename to resources/python/visualisation/[VISUALISATION] Panda's Built In Vis/data1.csv diff --git a/[VISUALISATION] Panda's Built In Vis/data2.csv b/resources/python/visualisation/[VISUALISATION] Panda's Built In Vis/data2.csv similarity index 100% rename from [VISUALISATION] Panda's Built In Vis/data2.csv rename to resources/python/visualisation/[VISUALISATION] Panda's Built In Vis/data2.csv diff --git a/[VISUALISATION] Panda's Built In Vis/people.csv b/resources/python/visualisation/[VISUALISATION] Panda's Built In Vis/people.csv similarity index 100% rename from [VISUALISATION] Panda's Built In Vis/people.csv rename to resources/python/visualisation/[VISUALISATION] Panda's Built In Vis/people.csv diff --git a/[VISUALISATION] Statistical Plotting With Seaborn/Statistical Plotting With Seaborn.ipynb b/resources/python/visualisation/[VISUALISATION] Statistical Plotting With Seaborn/Statistical Plotting With Seaborn.ipynb similarity index 100% rename from [VISUALISATION] Statistical Plotting With Seaborn/Statistical Plotting With Seaborn.ipynb rename to resources/python/visualisation/[VISUALISATION] Statistical Plotting With Seaborn/Statistical Plotting With Seaborn.ipynb diff --git a/[VISUALISATION] Statistical Plotting With Seaborn/header.png b/resources/python/visualisation/[VISUALISATION] Statistical Plotting With Seaborn/header.png similarity index 100% rename from [VISUALISATION] Statistical Plotting With Seaborn/header.png rename to resources/python/visualisation/[VISUALISATION] Statistical Plotting With Seaborn/header.png diff --git a/web/CNAME b/web/CNAME deleted file mode 100644 index aeefe99..0000000 --- a/web/CNAME +++ /dev/null @@ -1 +0,0 @@ -cdtpy.org diff --git a/web/README.md b/web/README.md deleted file mode 100644 index 5a6de85..0000000 --- a/web/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Sass Starter Pack - -A light package for compiling Sass and running a dev server - -### Version -1.0.0 - -## Usage - - -### Installation - -Install the dependencies (gulp, gulp-sass, browser-sync) - -```sh -$ npm install -``` - -### Run - -This will watch your sass files, compile them and run your dev server at http://localhost:3000 - -```sh -$ npm start -``` \ No newline at end of file diff --git a/web/gulpfile.js b/web/gulpfile.js deleted file mode 100644 index 4f67661..0000000 --- a/web/gulpfile.js +++ /dev/null @@ -1,33 +0,0 @@ -const gulp = require('gulp'); -const browserSync = require('browser-sync').create(); -const sass = require('gulp-sass'); -const jade = require('gulp-jade'); - -// Compile Sass & Inject Into Browser -gulp.task('sass', function() { - return gulp.src(['../docs/scss/*.scss']) - .pipe(sass()) - .pipe(gulp.dest("../docs/css")) - .pipe(browserSync.stream()); -}); - -gulp.task('jade', function() { - return gulp.src(["../docs/jade/*.jade"]) - .pipe(jade({pretty: true})) - .pipe(gulp.dest("../docs")) -}) - - -// Watch Sass & Serve -gulp.task('serve', ['sass', 'jade'], function() { - browserSync.init({ - server: "./../docs" - }); - - gulp.watch(['../docs/scss/*.scss'], ['sass']); - gulp.watch(['../docs/jade/*.jade'], ['jade']); - gulp.watch("../docs/*.html").on('change', browserSync.reload); -}); - -// Default Task -gulp.task('default', ['serve']); diff --git a/web/node_modules/.bin/acorn b/web/node_modules/.bin/acorn deleted file mode 120000 index cf76760..0000000 --- a/web/node_modules/.bin/acorn +++ /dev/null @@ -1 +0,0 @@ -../acorn/bin/acorn \ No newline at end of file diff --git a/web/node_modules/.bin/browser-sync b/web/node_modules/.bin/browser-sync deleted file mode 120000 index c83515b..0000000 --- a/web/node_modules/.bin/browser-sync +++ /dev/null @@ -1 +0,0 @@ -../browser-sync/bin/browser-sync.js \ No newline at end of file diff --git a/web/node_modules/.bin/cleancss b/web/node_modules/.bin/cleancss deleted file mode 120000 index 2a3439e..0000000 --- a/web/node_modules/.bin/cleancss +++ /dev/null @@ -1 +0,0 @@ -../clean-css/bin/cleancss \ No newline at end of file diff --git a/web/node_modules/.bin/dev-ip b/web/node_modules/.bin/dev-ip deleted file mode 120000 index 138e5ac..0000000 --- a/web/node_modules/.bin/dev-ip +++ /dev/null @@ -1 +0,0 @@ -../dev-ip/lib/dev-ip.js \ No newline at end of file diff --git a/web/node_modules/.bin/express b/web/node_modules/.bin/express deleted file mode 120000 index b741d99..0000000 --- a/web/node_modules/.bin/express +++ /dev/null @@ -1 +0,0 @@ -../express/bin/express \ No newline at end of file diff --git a/web/node_modules/.bin/gulp b/web/node_modules/.bin/gulp deleted file mode 120000 index 5de7332..0000000 --- a/web/node_modules/.bin/gulp +++ /dev/null @@ -1 +0,0 @@ -../gulp/bin/gulp.js \ No newline at end of file diff --git a/web/node_modules/.bin/in-install b/web/node_modules/.bin/in-install deleted file mode 120000 index 08c9689..0000000 --- a/web/node_modules/.bin/in-install +++ /dev/null @@ -1 +0,0 @@ -../in-publish/in-install.js \ No newline at end of file diff --git a/web/node_modules/.bin/in-publish b/web/node_modules/.bin/in-publish deleted file mode 120000 index ae9e779..0000000 --- a/web/node_modules/.bin/in-publish +++ /dev/null @@ -1 +0,0 @@ -../in-publish/in-publish.js \ No newline at end of file diff --git a/web/node_modules/.bin/jade b/web/node_modules/.bin/jade deleted file mode 120000 index 65a3bac..0000000 --- a/web/node_modules/.bin/jade +++ /dev/null @@ -1 +0,0 @@ -../jade/bin/jade.js \ No newline at end of file diff --git a/web/node_modules/.bin/lt b/web/node_modules/.bin/lt deleted file mode 120000 index f79fff9..0000000 --- a/web/node_modules/.bin/lt +++ /dev/null @@ -1 +0,0 @@ -../localtunnel/bin/client \ No newline at end of file diff --git a/web/node_modules/.bin/node-gyp b/web/node_modules/.bin/node-gyp deleted file mode 120000 index 9b31a4f..0000000 --- a/web/node_modules/.bin/node-gyp +++ /dev/null @@ -1 +0,0 @@ -../node-gyp/bin/node-gyp.js \ No newline at end of file diff --git a/web/node_modules/.bin/node-sass b/web/node_modules/.bin/node-sass deleted file mode 120000 index a4b0134..0000000 --- a/web/node_modules/.bin/node-sass +++ /dev/null @@ -1 +0,0 @@ -../node-sass/bin/node-sass \ No newline at end of file diff --git a/web/node_modules/.bin/nopt b/web/node_modules/.bin/nopt deleted file mode 120000 index 6b6566e..0000000 --- a/web/node_modules/.bin/nopt +++ /dev/null @@ -1 +0,0 @@ -../nopt/bin/nopt.js \ No newline at end of file diff --git a/web/node_modules/.bin/not-in-install b/web/node_modules/.bin/not-in-install deleted file mode 120000 index dbfcf38..0000000 --- a/web/node_modules/.bin/not-in-install +++ /dev/null @@ -1 +0,0 @@ -../in-publish/not-in-install.js \ No newline at end of file diff --git a/web/node_modules/.bin/not-in-publish b/web/node_modules/.bin/not-in-publish deleted file mode 120000 index 5cc2922..0000000 --- a/web/node_modules/.bin/not-in-publish +++ /dev/null @@ -1 +0,0 @@ -../in-publish/not-in-publish.js \ No newline at end of file diff --git a/web/node_modules/.bin/rimraf b/web/node_modules/.bin/rimraf deleted file mode 120000 index 4cd49a4..0000000 --- a/web/node_modules/.bin/rimraf +++ /dev/null @@ -1 +0,0 @@ -../rimraf/bin.js \ No newline at end of file diff --git a/web/node_modules/.bin/sassgraph b/web/node_modules/.bin/sassgraph deleted file mode 120000 index 901ada9..0000000 --- a/web/node_modules/.bin/sassgraph +++ /dev/null @@ -1 +0,0 @@ -../sass-graph/bin/sassgraph \ No newline at end of file diff --git a/web/node_modules/.bin/semver b/web/node_modules/.bin/semver deleted file mode 120000 index 317eb29..0000000 --- a/web/node_modules/.bin/semver +++ /dev/null @@ -1 +0,0 @@ -../semver/bin/semver \ No newline at end of file diff --git a/web/node_modules/.bin/sshpk-conv b/web/node_modules/.bin/sshpk-conv deleted file mode 120000 index a2a295c..0000000 --- a/web/node_modules/.bin/sshpk-conv +++ /dev/null @@ -1 +0,0 @@ -../sshpk/bin/sshpk-conv \ No newline at end of file diff --git a/web/node_modules/.bin/sshpk-sign b/web/node_modules/.bin/sshpk-sign deleted file mode 120000 index 766b9b3..0000000 --- a/web/node_modules/.bin/sshpk-sign +++ /dev/null @@ -1 +0,0 @@ -../sshpk/bin/sshpk-sign \ No newline at end of file diff --git a/web/node_modules/.bin/sshpk-verify b/web/node_modules/.bin/sshpk-verify deleted file mode 120000 index bfd7e3a..0000000 --- a/web/node_modules/.bin/sshpk-verify +++ /dev/null @@ -1 +0,0 @@ -../sshpk/bin/sshpk-verify \ No newline at end of file diff --git a/web/node_modules/.bin/strip-indent b/web/node_modules/.bin/strip-indent deleted file mode 120000 index dddee7e..0000000 --- a/web/node_modules/.bin/strip-indent +++ /dev/null @@ -1 +0,0 @@ -../strip-indent/cli.js \ No newline at end of file diff --git a/web/node_modules/.bin/throttleproxy b/web/node_modules/.bin/throttleproxy deleted file mode 120000 index 2ec6e30..0000000 --- a/web/node_modules/.bin/throttleproxy +++ /dev/null @@ -1 +0,0 @@ -../stream-throttle/bin/throttleproxy.js \ No newline at end of file diff --git a/web/node_modules/.bin/uglifyjs b/web/node_modules/.bin/uglifyjs deleted file mode 120000 index fef3468..0000000 --- a/web/node_modules/.bin/uglifyjs +++ /dev/null @@ -1 +0,0 @@ -../uglify-js/bin/uglifyjs \ No newline at end of file diff --git a/web/node_modules/.bin/user-home b/web/node_modules/.bin/user-home deleted file mode 120000 index d72d76b..0000000 --- a/web/node_modules/.bin/user-home +++ /dev/null @@ -1 +0,0 @@ -../user-home/cli.js \ No newline at end of file diff --git a/web/node_modules/.bin/uuid b/web/node_modules/.bin/uuid deleted file mode 120000 index b3e45bc..0000000 --- a/web/node_modules/.bin/uuid +++ /dev/null @@ -1 +0,0 @@ -../uuid/bin/uuid \ No newline at end of file diff --git a/web/node_modules/.bin/weinre b/web/node_modules/.bin/weinre deleted file mode 120000 index 53c7151..0000000 --- a/web/node_modules/.bin/weinre +++ /dev/null @@ -1 +0,0 @@ -../weinre/weinre \ No newline at end of file diff --git a/web/node_modules/.bin/which b/web/node_modules/.bin/which deleted file mode 120000 index f62471c..0000000 --- a/web/node_modules/.bin/which +++ /dev/null @@ -1 +0,0 @@ -../which/bin/which \ No newline at end of file diff --git a/web/node_modules/.bin/window-size b/web/node_modules/.bin/window-size deleted file mode 120000 index e84c8ec..0000000 --- a/web/node_modules/.bin/window-size +++ /dev/null @@ -1 +0,0 @@ -../window-size/cli.js \ No newline at end of file diff --git a/web/node_modules/abbrev/LICENSE b/web/node_modules/abbrev/LICENSE deleted file mode 100644 index 9bcfa9d..0000000 --- a/web/node_modules/abbrev/LICENSE +++ /dev/null @@ -1,46 +0,0 @@ -This software is dual-licensed under the ISC and MIT licenses. -You may use this software under EITHER of the following licenses. - ----------- - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - ----------- - -Copyright Isaac Z. Schlueter and Contributors -All rights reserved. - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/web/node_modules/abbrev/README.md b/web/node_modules/abbrev/README.md deleted file mode 100644 index 99746fe..0000000 --- a/web/node_modules/abbrev/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# abbrev-js - -Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev). - -Usage: - - var abbrev = require("abbrev"); - abbrev("foo", "fool", "folding", "flop"); - - // returns: - { fl: 'flop' - , flo: 'flop' - , flop: 'flop' - , fol: 'folding' - , fold: 'folding' - , foldi: 'folding' - , foldin: 'folding' - , folding: 'folding' - , foo: 'foo' - , fool: 'fool' - } - -This is handy for command-line scripts, or other cases where you want to be able to accept shorthands. diff --git a/web/node_modules/abbrev/abbrev.js b/web/node_modules/abbrev/abbrev.js deleted file mode 100644 index 7b1dc5d..0000000 --- a/web/node_modules/abbrev/abbrev.js +++ /dev/null @@ -1,61 +0,0 @@ -module.exports = exports = abbrev.abbrev = abbrev - -abbrev.monkeyPatch = monkeyPatch - -function monkeyPatch () { - Object.defineProperty(Array.prototype, 'abbrev', { - value: function () { return abbrev(this) }, - enumerable: false, configurable: true, writable: true - }) - - Object.defineProperty(Object.prototype, 'abbrev', { - value: function () { return abbrev(Object.keys(this)) }, - enumerable: false, configurable: true, writable: true - }) -} - -function abbrev (list) { - if (arguments.length !== 1 || !Array.isArray(list)) { - list = Array.prototype.slice.call(arguments, 0) - } - for (var i = 0, l = list.length, args = [] ; i < l ; i ++) { - args[i] = typeof list[i] === "string" ? list[i] : String(list[i]) - } - - // sort them lexicographically, so that they're next to their nearest kin - args = args.sort(lexSort) - - // walk through each, seeing how much it has in common with the next and previous - var abbrevs = {} - , prev = "" - for (var i = 0, l = args.length ; i < l ; i ++) { - var current = args[i] - , next = args[i + 1] || "" - , nextMatches = true - , prevMatches = true - if (current === next) continue - for (var j = 0, cl = current.length ; j < cl ; j ++) { - var curChar = current.charAt(j) - nextMatches = nextMatches && curChar === next.charAt(j) - prevMatches = prevMatches && curChar === prev.charAt(j) - if (!nextMatches && !prevMatches) { - j ++ - break - } - } - prev = current - if (j === cl) { - abbrevs[current] = current - continue - } - for (var a = current.substr(0, j) ; j <= cl ; j ++) { - abbrevs[a] = current - a += current.charAt(j) - } - } - return abbrevs -} - -function lexSort (a, b) { - return a === b ? 0 : a > b ? 1 : -1 -} diff --git a/web/node_modules/abbrev/package.json b/web/node_modules/abbrev/package.json deleted file mode 100644 index 14a1861..0000000 --- a/web/node_modules/abbrev/package.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "_args": [ - [ - "abbrev@1.1.1", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "abbrev@1.1.1", - "_id": "abbrev@1.1.1", - "_inBundle": false, - "_integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "_location": "/abbrev", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "abbrev@1.1.1", - "name": "abbrev", - "escapedName": "abbrev", - "rawSpec": "1.1.1", - "saveSpec": null, - "fetchSpec": "1.1.1" - }, - "_requiredBy": [ - "/nopt" - ], - "_resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "_spec": "1.1.1", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me" - }, - "bugs": { - "url": "https://github.com/isaacs/abbrev-js/issues" - }, - "description": "Like ruby's abbrev module, but in js", - "devDependencies": { - "tap": "^10.1" - }, - "files": [ - "abbrev.js" - ], - "homepage": "https://github.com/isaacs/abbrev-js#readme", - "license": "ISC", - "main": "abbrev.js", - "name": "abbrev", - "repository": { - "type": "git", - "url": "git+ssh://git@github.com/isaacs/abbrev-js.git" - }, - "scripts": { - "postpublish": "git push origin --all; git push origin --tags", - "postversion": "npm publish", - "preversion": "npm test", - "test": "tap test.js --100" - }, - "version": "1.1.1" -} diff --git a/web/node_modules/accepts/HISTORY.md b/web/node_modules/accepts/HISTORY.md deleted file mode 100644 index aaf5281..0000000 --- a/web/node_modules/accepts/HISTORY.md +++ /dev/null @@ -1,218 +0,0 @@ -1.3.4 / 2017-08-22 -================== - - * deps: mime-types@~2.1.16 - - deps: mime-db@~1.29.0 - -1.3.3 / 2016-05-02 -================== - - * deps: mime-types@~2.1.11 - - deps: mime-db@~1.23.0 - * deps: negotiator@0.6.1 - - perf: improve `Accept` parsing speed - - perf: improve `Accept-Charset` parsing speed - - perf: improve `Accept-Encoding` parsing speed - - perf: improve `Accept-Language` parsing speed - -1.3.2 / 2016-03-08 -================== - - * deps: mime-types@~2.1.10 - - Fix extension of `application/dash+xml` - - Update primary extension for `audio/mp4` - - deps: mime-db@~1.22.0 - -1.3.1 / 2016-01-19 -================== - - * deps: mime-types@~2.1.9 - - deps: mime-db@~1.21.0 - -1.3.0 / 2015-09-29 -================== - - * deps: mime-types@~2.1.7 - - deps: mime-db@~1.19.0 - * deps: negotiator@0.6.0 - - Fix including type extensions in parameters in `Accept` parsing - - Fix parsing `Accept` parameters with quoted equals - - Fix parsing `Accept` parameters with quoted semicolons - - Lazy-load modules from main entry point - - perf: delay type concatenation until needed - - perf: enable strict mode - - perf: hoist regular expressions - - perf: remove closures getting spec properties - - perf: remove a closure from media type parsing - - perf: remove property delete from media type parsing - -1.2.13 / 2015-09-06 -=================== - - * deps: mime-types@~2.1.6 - - deps: mime-db@~1.18.0 - -1.2.12 / 2015-07-30 -=================== - - * deps: mime-types@~2.1.4 - - deps: mime-db@~1.16.0 - -1.2.11 / 2015-07-16 -=================== - - * deps: mime-types@~2.1.3 - - deps: mime-db@~1.15.0 - -1.2.10 / 2015-07-01 -=================== - - * deps: mime-types@~2.1.2 - - deps: mime-db@~1.14.0 - -1.2.9 / 2015-06-08 -================== - - * deps: mime-types@~2.1.1 - - perf: fix deopt during mapping - -1.2.8 / 2015-06-07 -================== - - * deps: mime-types@~2.1.0 - - deps: mime-db@~1.13.0 - * perf: avoid argument reassignment & argument slice - * perf: avoid negotiator recursive construction - * perf: enable strict mode - * perf: remove unnecessary bitwise operator - -1.2.7 / 2015-05-10 -================== - - * deps: negotiator@0.5.3 - - Fix media type parameter matching to be case-insensitive - -1.2.6 / 2015-05-07 -================== - - * deps: mime-types@~2.0.11 - - deps: mime-db@~1.9.1 - * deps: negotiator@0.5.2 - - Fix comparing media types with quoted values - - Fix splitting media types with quoted commas - -1.2.5 / 2015-03-13 -================== - - * deps: mime-types@~2.0.10 - - deps: mime-db@~1.8.0 - -1.2.4 / 2015-02-14 -================== - - * Support Node.js 0.6 - * deps: mime-types@~2.0.9 - - deps: mime-db@~1.7.0 - * deps: negotiator@0.5.1 - - Fix preference sorting to be stable for long acceptable lists - -1.2.3 / 2015-01-31 -================== - - * deps: mime-types@~2.0.8 - - deps: mime-db@~1.6.0 - -1.2.2 / 2014-12-30 -================== - - * deps: mime-types@~2.0.7 - - deps: mime-db@~1.5.0 - -1.2.1 / 2014-12-30 -================== - - * deps: mime-types@~2.0.5 - - deps: mime-db@~1.3.1 - -1.2.0 / 2014-12-19 -================== - - * deps: negotiator@0.5.0 - - Fix list return order when large accepted list - - Fix missing identity encoding when q=0 exists - - Remove dynamic building of Negotiator class - -1.1.4 / 2014-12-10 -================== - - * deps: mime-types@~2.0.4 - - deps: mime-db@~1.3.0 - -1.1.3 / 2014-11-09 -================== - - * deps: mime-types@~2.0.3 - - deps: mime-db@~1.2.0 - -1.1.2 / 2014-10-14 -================== - - * deps: negotiator@0.4.9 - - Fix error when media type has invalid parameter - -1.1.1 / 2014-09-28 -================== - - * deps: mime-types@~2.0.2 - - deps: mime-db@~1.1.0 - * deps: negotiator@0.4.8 - - Fix all negotiations to be case-insensitive - - Stable sort preferences of same quality according to client order - -1.1.0 / 2014-09-02 -================== - - * update `mime-types` - -1.0.7 / 2014-07-04 -================== - - * Fix wrong type returned from `type` when match after unknown extension - -1.0.6 / 2014-06-24 -================== - - * deps: negotiator@0.4.7 - -1.0.5 / 2014-06-20 -================== - - * fix crash when unknown extension given - -1.0.4 / 2014-06-19 -================== - - * use `mime-types` - -1.0.3 / 2014-06-11 -================== - - * deps: negotiator@0.4.6 - - Order by specificity when quality is the same - -1.0.2 / 2014-05-29 -================== - - * Fix interpretation when header not in request - * deps: pin negotiator@0.4.5 - -1.0.1 / 2014-01-18 -================== - - * Identity encoding isn't always acceptable - * deps: negotiator@~0.4.0 - -1.0.0 / 2013-12-27 -================== - - * Genesis diff --git a/web/node_modules/accepts/LICENSE b/web/node_modules/accepts/LICENSE deleted file mode 100644 index 0616607..0000000 --- a/web/node_modules/accepts/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -(The MIT License) - -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2015 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/web/node_modules/accepts/README.md b/web/node_modules/accepts/README.md deleted file mode 100644 index 6a2749a..0000000 --- a/web/node_modules/accepts/README.md +++ /dev/null @@ -1,143 +0,0 @@ -# accepts - -[![NPM Version][npm-image]][npm-url] -[![NPM Downloads][downloads-image]][downloads-url] -[![Node.js Version][node-version-image]][node-version-url] -[![Build Status][travis-image]][travis-url] -[![Test Coverage][coveralls-image]][coveralls-url] - -Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator). -Extracted from [koa](https://www.npmjs.com/package/koa) for general use. - -In addition to negotiator, it allows: - -- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])` - as well as `('text/html', 'application/json')`. -- Allows type shorthands such as `json`. -- Returns `false` when no types match -- Treats non-existent headers as `*` - -## Installation - -This is a [Node.js](https://nodejs.org/en/) module available through the -[npm registry](https://www.npmjs.com/). Installation is done using the -[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): - -```sh -$ npm install accepts -``` - -## API - - - -```js -var accepts = require('accepts') -``` - -### accepts(req) - -Create a new `Accepts` object for the given `req`. - -#### .charset(charsets) - -Return the first accepted charset. If nothing in `charsets` is accepted, -then `false` is returned. - -#### .charsets() - -Return the charsets that the request accepts, in the order of the client's -preference (most preferred first). - -#### .encoding(encodings) - -Return the first accepted encoding. If nothing in `encodings` is accepted, -then `false` is returned. - -#### .encodings() - -Return the encodings that the request accepts, in the order of the client's -preference (most preferred first). - -#### .language(languages) - -Return the first accepted language. If nothing in `languages` is accepted, -then `false` is returned. - -#### .languages() - -Return the languages that the request accepts, in the order of the client's -preference (most preferred first). - -#### .type(types) - -Return the first accepted type (and it is returned as the same text as what -appears in the `types` array). If nothing in `types` is accepted, then `false` -is returned. - -The `types` array can contain full MIME types or file extensions. Any value -that is not a full MIME types is passed to `require('mime-types').lookup`. - -#### .types() - -Return the types that the request accepts, in the order of the client's -preference (most preferred first). - -## Examples - -### Simple type negotiation - -This simple example shows how to use `accepts` to return a different typed -respond body based on what the client wants to accept. The server lists it's -preferences in order and will get back the best match between the client and -server. - -```js -var accepts = require('accepts') -var http = require('http') - -function app (req, res) { - var accept = accepts(req) - - // the order of this list is significant; should be server preferred order - switch (accept.type(['json', 'html'])) { - case 'json': - res.setHeader('Content-Type', 'application/json') - res.write('{"hello":"world!"}') - break - case 'html': - res.setHeader('Content-Type', 'text/html') - res.write('hello, world!') - break - default: - // the fallback is text/plain, so no need to specify it above - res.setHeader('Content-Type', 'text/plain') - res.write('hello, world!') - break - } - - res.end() -} - -http.createServer(app).listen(3000) -``` - -You can test this out with the cURL program: -```sh -curl -I -H'Accept: text/html' http://localhost:3000/ -``` - -## License - -[MIT](LICENSE) - -[npm-image]: https://img.shields.io/npm/v/accepts.svg -[npm-url]: https://npmjs.org/package/accepts -[node-version-image]: https://img.shields.io/node/v/accepts.svg -[node-version-url]: https://nodejs.org/en/download/ -[travis-image]: https://img.shields.io/travis/jshttp/accepts/master.svg -[travis-url]: https://travis-ci.org/jshttp/accepts -[coveralls-image]: https://img.shields.io/coveralls/jshttp/accepts/master.svg -[coveralls-url]: https://coveralls.io/r/jshttp/accepts -[downloads-image]: https://img.shields.io/npm/dm/accepts.svg -[downloads-url]: https://npmjs.org/package/accepts diff --git a/web/node_modules/accepts/index.js b/web/node_modules/accepts/index.js deleted file mode 100644 index e9b2f63..0000000 --- a/web/node_modules/accepts/index.js +++ /dev/null @@ -1,238 +0,0 @@ -/*! - * accepts - * Copyright(c) 2014 Jonathan Ong - * Copyright(c) 2015 Douglas Christopher Wilson - * MIT Licensed - */ - -'use strict' - -/** - * Module dependencies. - * @private - */ - -var Negotiator = require('negotiator') -var mime = require('mime-types') - -/** - * Module exports. - * @public - */ - -module.exports = Accepts - -/** - * Create a new Accepts object for the given req. - * - * @param {object} req - * @public - */ - -function Accepts (req) { - if (!(this instanceof Accepts)) { - return new Accepts(req) - } - - this.headers = req.headers - this.negotiator = new Negotiator(req) -} - -/** - * Check if the given `type(s)` is acceptable, returning - * the best match when true, otherwise `undefined`, in which - * case you should respond with 406 "Not Acceptable". - * - * The `type` value may be a single mime type string - * such as "application/json", the extension name - * such as "json" or an array `["json", "html", "text/plain"]`. When a list - * or array is given the _best_ match, if any is returned. - * - * Examples: - * - * // Accept: text/html - * this.types('html'); - * // => "html" - * - * // Accept: text/*, application/json - * this.types('html'); - * // => "html" - * this.types('text/html'); - * // => "text/html" - * this.types('json', 'text'); - * // => "json" - * this.types('application/json'); - * // => "application/json" - * - * // Accept: text/*, application/json - * this.types('image/png'); - * this.types('png'); - * // => undefined - * - * // Accept: text/*;q=.5, application/json - * this.types(['html', 'json']); - * this.types('html', 'json'); - * // => "json" - * - * @param {String|Array} types... - * @return {String|Array|Boolean} - * @public - */ - -Accepts.prototype.type = -Accepts.prototype.types = function (types_) { - var types = types_ - - // support flattened arguments - if (types && !Array.isArray(types)) { - types = new Array(arguments.length) - for (var i = 0; i < types.length; i++) { - types[i] = arguments[i] - } - } - - // no types, return all requested types - if (!types || types.length === 0) { - return this.negotiator.mediaTypes() - } - - // no accept header, return first given type - if (!this.headers.accept) { - return types[0] - } - - var mimes = types.map(extToMime) - var accepts = this.negotiator.mediaTypes(mimes.filter(validMime)) - var first = accepts[0] - - return first - ? types[mimes.indexOf(first)] - : false -} - -/** - * Return accepted encodings or best fit based on `encodings`. - * - * Given `Accept-Encoding: gzip, deflate` - * an array sorted by quality is returned: - * - * ['gzip', 'deflate'] - * - * @param {String|Array} encodings... - * @return {String|Array} - * @public - */ - -Accepts.prototype.encoding = -Accepts.prototype.encodings = function (encodings_) { - var encodings = encodings_ - - // support flattened arguments - if (encodings && !Array.isArray(encodings)) { - encodings = new Array(arguments.length) - for (var i = 0; i < encodings.length; i++) { - encodings[i] = arguments[i] - } - } - - // no encodings, return all requested encodings - if (!encodings || encodings.length === 0) { - return this.negotiator.encodings() - } - - return this.negotiator.encodings(encodings)[0] || false -} - -/** - * Return accepted charsets or best fit based on `charsets`. - * - * Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5` - * an array sorted by quality is returned: - * - * ['utf-8', 'utf-7', 'iso-8859-1'] - * - * @param {String|Array} charsets... - * @return {String|Array} - * @public - */ - -Accepts.prototype.charset = -Accepts.prototype.charsets = function (charsets_) { - var charsets = charsets_ - - // support flattened arguments - if (charsets && !Array.isArray(charsets)) { - charsets = new Array(arguments.length) - for (var i = 0; i < charsets.length; i++) { - charsets[i] = arguments[i] - } - } - - // no charsets, return all requested charsets - if (!charsets || charsets.length === 0) { - return this.negotiator.charsets() - } - - return this.negotiator.charsets(charsets)[0] || false -} - -/** - * Return accepted languages or best fit based on `langs`. - * - * Given `Accept-Language: en;q=0.8, es, pt` - * an array sorted by quality is returned: - * - * ['es', 'pt', 'en'] - * - * @param {String|Array} langs... - * @return {Array|String} - * @public - */ - -Accepts.prototype.lang = -Accepts.prototype.langs = -Accepts.prototype.language = -Accepts.prototype.languages = function (languages_) { - var languages = languages_ - - // support flattened arguments - if (languages && !Array.isArray(languages)) { - languages = new Array(arguments.length) - for (var i = 0; i < languages.length; i++) { - languages[i] = arguments[i] - } - } - - // no languages, return all requested languages - if (!languages || languages.length === 0) { - return this.negotiator.languages() - } - - return this.negotiator.languages(languages)[0] || false -} - -/** - * Convert extnames to mime. - * - * @param {String} type - * @return {String} - * @private - */ - -function extToMime (type) { - return type.indexOf('/') === -1 - ? mime.lookup(type) - : type -} - -/** - * Check if mime is valid. - * - * @param {String} type - * @return {String} - * @private - */ - -function validMime (type) { - return typeof type === 'string' -} diff --git a/web/node_modules/accepts/package.json b/web/node_modules/accepts/package.json deleted file mode 100644 index 831f72c..0000000 --- a/web/node_modules/accepts/package.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "_args": [ - [ - "accepts@1.3.4", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "accepts@1.3.4", - "_id": "accepts@1.3.4", - "_inBundle": false, - "_integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", - "_location": "/accepts", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "accepts@1.3.4", - "name": "accepts", - "escapedName": "accepts", - "rawSpec": "1.3.4", - "saveSpec": null, - "fetchSpec": "1.3.4" - }, - "_requiredBy": [ - "/serve-index" - ], - "_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", - "_spec": "1.3.4", - "_where": "/home/treharne/Documents/web/cdt-py", - "bugs": { - "url": "https://github.com/jshttp/accepts/issues" - }, - "contributors": [ - { - "name": "Douglas Christopher Wilson", - "email": "doug@somethingdoug.com" - }, - { - "name": "Jonathan Ong", - "email": "me@jongleberry.com", - "url": "http://jongleberry.com" - } - ], - "dependencies": { - "mime-types": "~2.1.16", - "negotiator": "0.6.1" - }, - "description": "Higher-level content negotiation", - "devDependencies": { - "eslint": "3.19.0", - "eslint-config-standard": "10.2.1", - "eslint-plugin-import": "2.7.0", - "eslint-plugin-markdown": "1.0.0-beta.6", - "eslint-plugin-node": "5.1.1", - "eslint-plugin-promise": "3.5.0", - "eslint-plugin-standard": "3.0.1", - "istanbul": "0.4.5", - "mocha": "~1.21.5" - }, - "engines": { - "node": ">= 0.6" - }, - "files": [ - "LICENSE", - "HISTORY.md", - "index.js" - ], - "homepage": "https://github.com/jshttp/accepts#readme", - "keywords": [ - "content", - "negotiation", - "accept", - "accepts" - ], - "license": "MIT", - "name": "accepts", - "repository": { - "type": "git", - "url": "git+https://github.com/jshttp/accepts.git" - }, - "scripts": { - "lint": "eslint --plugin markdown --ext js,md .", - "test": "mocha --reporter spec --check-leaks --bail test/", - "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", - "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" - }, - "version": "1.3.4" -} diff --git a/web/node_modules/acorn-globals/LICENSE b/web/node_modules/acorn-globals/LICENSE deleted file mode 100644 index 27cc9f3..0000000 --- a/web/node_modules/acorn-globals/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2014 Forbes Lindesay - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/web/node_modules/acorn-globals/README.md b/web/node_modules/acorn-globals/README.md deleted file mode 100644 index d8cd372..0000000 --- a/web/node_modules/acorn-globals/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# acorn-globals - -Detect global variables in JavaScript using acorn - -[![Build Status](https://img.shields.io/travis/ForbesLindesay/acorn-globals/master.svg)](https://travis-ci.org/ForbesLindesay/acorn-globals) -[![Dependency Status](https://img.shields.io/david/ForbesLindesay/acorn-globals.svg)](https://david-dm.org/ForbesLindesay/acorn-globals) -[![NPM version](https://img.shields.io/npm/v/acorn-globals.svg)](https://www.npmjs.org/package/acorn-globals) - -## Installation - - npm install acorn-globals - -## Usage - -detect.js - -```js -var fs = require('fs'); -var detect = require('acorn-globals'); - -var src = fs.readFileSync(__dirname + '/input.js', 'utf8'); - -var scope = detect(src); -console.dir(scope); -``` - -input.js - -```js -var x = 5; -var y = 3, z = 2; - -w.foo(); -w = 2; - -RAWR=444; -RAWR.foo(); - -BLARG=3; - -foo(function () { - var BAR = 3; - process.nextTick(function (ZZZZZZZZZZZZ) { - console.log('beep boop'); - var xyz = 4; - x += 10; - x.zzzzzz; - ZZZ=6; - }); - function doom () { - } - ZZZ.foo(); - -}); - -console.log(xyz); -``` - -output: - -``` -$ node example/detect.js -[ { name: 'BLARG', nodes: [ [Object] ] }, - { name: 'RAWR', nodes: [ [Object], [Object] ] }, - { name: 'ZZZ', nodes: [ [Object], [Object] ] }, - { name: 'console', nodes: [ [Object], [Object] ] }, - { name: 'foo', nodes: [ [Object] ] }, - { name: 'process', nodes: [ [Object] ] }, - { name: 'w', nodes: [ [Object], [Object] ] }, - { name: 'xyz', nodes: [ [Object] ] } ] -``` - - -## License - - MIT diff --git a/web/node_modules/acorn-globals/index.js b/web/node_modules/acorn-globals/index.js deleted file mode 100644 index ff924c9..0000000 --- a/web/node_modules/acorn-globals/index.js +++ /dev/null @@ -1,180 +0,0 @@ -'use strict'; - -var acorn = require('acorn'); -var walk = require('acorn/dist/walk'); - -function isScope(node) { - return node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression' || node.type === 'Program'; -} -function isBlockScope(node) { - return node.type === 'BlockStatement' || isScope(node); -} - -function declaresArguments(node) { - return node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration'; -} - -function declaresThis(node) { - return node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration'; -} - -function reallyParse(source) { - try { - return acorn.parse(source, { - ecmaVersion: 6, - allowReturnOutsideFunction: true, - allowImportExportEverywhere: true, - allowHashBang: true - }); - } catch (ex) { - return acorn.parse(source, { - ecmaVersion: 5, - allowReturnOutsideFunction: true, - allowImportExportEverywhere: true, - allowHashBang: true - }); - } -} -module.exports = findGlobals; -module.exports.parse = reallyParse; -function findGlobals(source) { - var globals = []; - var ast; - // istanbul ignore else - if (typeof source === 'string') { - ast = reallyParse(source); - } else { - ast = source; - } - // istanbul ignore if - if (!(ast && typeof ast === 'object' && ast.type === 'Program')) { - throw new TypeError('Source must be either a string of JavaScript or an acorn AST'); - } - var declareFunction = function (node) { - var fn = node; - fn.locals = fn.locals || {}; - node.params.forEach(function (node) { - declarePattern(node, fn); - }); - if (node.id) { - fn.locals[node.id.name] = true; - } - } - var declarePattern = function (node, parent) { - switch (node.type) { - case 'Identifier': - parent.locals[node.name] = true; - break; - case 'ObjectPattern': - node.properties.forEach(function (node) { - declarePattern(node.value, parent); - }); - break; - case 'ArrayPattern': - node.elements.forEach(function (node) { - if (node) declarePattern(node, parent); - }); - break; - case 'RestElement': - declarePattern(node.argument, parent); - break; - case 'AssignmentPattern': - declarePattern(node.left, parent); - break; - // istanbul ignore next - default: - throw new Error('Unrecognized pattern type: ' + node.type); - } - } - var declareModuleSpecifier = function (node, parents) { - ast.locals = ast.locals || {}; - ast.locals[node.local.name] = true; - } - walk.ancestor(ast, { - 'VariableDeclaration': function (node, parents) { - var parent = null; - for (var i = parents.length - 1; i >= 0 && parent === null; i--) { - if (node.kind === 'var' ? isScope(parents[i]) : isBlockScope(parents[i])) { - parent = parents[i]; - } - } - parent.locals = parent.locals || {}; - node.declarations.forEach(function (declaration) { - declarePattern(declaration.id, parent); - }); - }, - 'FunctionDeclaration': function (node, parents) { - var parent = null; - for (var i = parents.length - 2; i >= 0 && parent === null; i--) { - if (isScope(parents[i])) { - parent = parents[i]; - } - } - parent.locals = parent.locals || {}; - parent.locals[node.id.name] = true; - declareFunction(node); - }, - 'Function': declareFunction, - 'ClassDeclaration': function (node, parents) { - var parent = null; - for (var i = parents.length - 2; i >= 0 && parent === null; i--) { - if (isScope(parents[i])) { - parent = parents[i]; - } - } - parent.locals = parent.locals || {}; - parent.locals[node.id.name] = true; - }, - 'TryStatement': function (node) { - if (node.handler === null) return; - node.handler.body.locals = node.handler.body.locals || {}; - node.handler.body.locals[node.handler.param.name] = true; - }, - 'ImportDefaultSpecifier': declareModuleSpecifier, - 'ImportSpecifier': declareModuleSpecifier, - 'ImportNamespaceSpecifier': declareModuleSpecifier - }); - function identifier(node, parents) { - var name = node.name; - if (name === 'undefined') return; - for (var i = 0; i < parents.length; i++) { - if (name === 'arguments' && declaresArguments(parents[i])) { - return; - } - if (parents[i].locals && name in parents[i].locals) { - return; - } - } - if ( - parents[parents.length - 2] && - parents[parents.length - 2].type === 'TryStatement' && - parents[parents.length - 2].handler && - node === parents[parents.length - 2].handler.param - ) { - return; - } - node.parents = parents; - globals.push(node); - } - walk.ancestor(ast, { - 'VariablePattern': identifier, - 'Identifier': identifier, - 'ThisExpression': function (node, parents) { - for (var i = 0; i < parents.length; i++) { - if (declaresThis(parents[i])) { - return; - } - } - node.parents = parents; - globals.push(node); - } - }); - var groupedGlobals = {}; - globals.forEach(function (node) { - groupedGlobals[node.name] = (groupedGlobals[node.name] || []); - groupedGlobals[node.name].push(node); - }); - return Object.keys(groupedGlobals).sort().map(function (name) { - return {name: name, nodes: groupedGlobals[name]}; - }); -} diff --git a/web/node_modules/acorn-globals/package.json b/web/node_modules/acorn-globals/package.json deleted file mode 100644 index d74d650..0000000 --- a/web/node_modules/acorn-globals/package.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "_from": "acorn-globals@^1.0.3", - "_id": "acorn-globals@1.0.9", - "_inBundle": false, - "_integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=", - "_location": "/acorn-globals", - "_phantomChildren": {}, - "_requested": { - "type": "range", - "registry": true, - "raw": "acorn-globals@^1.0.3", - "name": "acorn-globals", - "escapedName": "acorn-globals", - "rawSpec": "^1.0.3", - "saveSpec": null, - "fetchSpec": "^1.0.3" - }, - "_requiredBy": [ - "/with" - ], - "_resolved": "http://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz", - "_shasum": "55bb5e98691507b74579d0513413217c380c54cf", - "_spec": "acorn-globals@^1.0.3", - "_where": "/home/treharne/Documents/web/cdt-py/node_modules/with", - "author": { - "name": "ForbesLindesay" - }, - "bugs": { - "url": "https://github.com/ForbesLindesay/acorn-globals/issues" - }, - "bundleDependencies": false, - "dependencies": { - "acorn": "^2.1.0" - }, - "deprecated": false, - "description": "Detect global variables in JavaScript using acorn", - "devDependencies": { - "testit": "^2.0.2" - }, - "files": [ - "index.js", - "LICENSE" - ], - "homepage": "https://github.com/ForbesLindesay/acorn-globals#readme", - "keywords": [ - "ast", - "variable", - "name", - "lexical", - "scope", - "local", - "global", - "implicit" - ], - "license": "MIT", - "name": "acorn-globals", - "repository": { - "type": "git", - "url": "git+https://github.com/ForbesLindesay/acorn-globals.git" - }, - "scripts": { - "test": "node test" - }, - "version": "1.0.9" -} diff --git a/web/node_modules/acorn/.editorconfig b/web/node_modules/acorn/.editorconfig deleted file mode 100644 index c14d5c6..0000000 --- a/web/node_modules/acorn/.editorconfig +++ /dev/null @@ -1,7 +0,0 @@ -root = true - -[*] -indent_style = space -indent_size = 2 -end_of_line = lf -insert_final_newline = true diff --git a/web/node_modules/acorn/.gitattributes b/web/node_modules/acorn/.gitattributes deleted file mode 100644 index fcadb2c..0000000 --- a/web/node_modules/acorn/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* text eol=lf diff --git a/web/node_modules/acorn/.npmignore b/web/node_modules/acorn/.npmignore deleted file mode 100644 index ecba291..0000000 --- a/web/node_modules/acorn/.npmignore +++ /dev/null @@ -1,3 +0,0 @@ -/.tern-port -/test -/local diff --git a/web/node_modules/acorn/.tern-project b/web/node_modules/acorn/.tern-project deleted file mode 100644 index 6718ce0..0000000 --- a/web/node_modules/acorn/.tern-project +++ /dev/null @@ -1,6 +0,0 @@ -{ - "plugins": { - "node": true, - "es_modules": true - } -} \ No newline at end of file diff --git a/web/node_modules/acorn/.travis.yml b/web/node_modules/acorn/.travis.yml deleted file mode 100644 index f50c379..0000000 --- a/web/node_modules/acorn/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: node_js -sudo: false -node_js: - - '0.10' - - '0.12' - - '4' diff --git a/web/node_modules/acorn/AUTHORS b/web/node_modules/acorn/AUTHORS deleted file mode 100644 index 0e8f48b..0000000 --- a/web/node_modules/acorn/AUTHORS +++ /dev/null @@ -1,43 +0,0 @@ -List of Acorn contributors. Updated before every release. - -Adrian Rakovsky -Alistair Braidwood -Andres Suarez -Aparajita Fishman -Arian Stolwijk -Artem Govorov -Brandon Mills -Charles Hughes -Conrad Irwin -David Bonnet -ForbesLindesay -Forbes Lindesay -Gilad Peleg -impinball -Ingvar Stepanyan -Jesse McCarthy -Jiaxing Wang -Joel Kemp -Johannes Herr -Jürg Lehni -keeyipchan -Kevin Kwok -krator -Marijn Haverbeke -Martin Carlberg -Mathias Bynens -Mathieu 'p01' Henri -Max Schaefer -Max Zerzouri -Mihai Bazon -Mike Rennie -Nick Fitzgerald -Oskar Schöldström -Paul Harper -Peter Rust -PlNG -r-e-d -Rich Harris -Sebastian McKenzie -Timothy Gu -zsjforcn diff --git a/web/node_modules/acorn/LICENSE b/web/node_modules/acorn/LICENSE deleted file mode 100644 index d4c7fc5..0000000 --- a/web/node_modules/acorn/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2012-2014 by various contributors (see AUTHORS) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/web/node_modules/acorn/README.md b/web/node_modules/acorn/README.md deleted file mode 100644 index acd39a8..0000000 --- a/web/node_modules/acorn/README.md +++ /dev/null @@ -1,396 +0,0 @@ -# Acorn - -[![Build Status](https://travis-ci.org/ternjs/acorn.svg?branch=master)](https://travis-ci.org/ternjs/acorn) -[![NPM version](https://img.shields.io/npm/v/acorn.svg)](https://www.npmjs.com/package/acorn) -[Author funding status: ![maintainer happiness](https://marijnhaverbeke.nl/fund/status_s.png?force)](https://marijnhaverbeke.nl/fund/) - -A tiny, fast JavaScript parser, written completely in JavaScript. - -## Community - -Acorn is open source software released under an -[MIT license](https://github.com/ternjs/acorn/blob/master/LICENSE). - -You are welcome to -[report bugs](https://github.com/ternjs/acorn/issues) or create pull -requests on [github](https://github.com/ternjs/acorn). For questions -and discussion, please use the -[Tern discussion forum](https://discuss.ternjs.net). - -## Installation - -The easiest way to install acorn is with [`npm`][npm]. - -[npm]: https://www.npmjs.com/ - -```sh -npm install acorn -``` - -Alternately, download the source. - -```sh -git clone https://github.com/ternjs/acorn.git -``` - -## Components - -When run in a CommonJS (node.js) or AMD environment, exported values -appear in the interfaces exposed by the individual files, as usual. -When loaded in the browser (Acorn works in any JS-enabled browser more -recent than IE5) without any kind of module management, a single -global object `acorn` will be defined, and all the exported properties -will be added to that. - -### Main parser - -This is implemented in `dist/acorn.js`, and is what you get when you -`require("acorn")` in node.js. - -**parse**`(input, options)` is used to parse a JavaScript program. -The `input` parameter is a string, `options` can be undefined or an -object setting some of the options listed below. The return value will -be an abstract syntax tree object as specified by the -[ESTree spec][estree]. - -When encountering a syntax error, the parser will raise a -`SyntaxError` object with a meaningful message. The error object will -have a `pos` property that indicates the character offset at which the -error occurred, and a `loc` object that contains a `{line, column}` -object referring to that same position. - -[estree]: https://github.com/estree/estree - -- **ecmaVersion**: Indicates the ECMAScript version to parse. Must be - either 3, 5, or 6. This influences support for strict mode, the set - of reserved words, and support for new syntax features. Default is 5. - -- **sourceType**: Indicate the mode the code should be parsed in. Can be - either `"script"` or `"module"`. - -- **onInsertedSemicolon**: If given a callback, that callback will be - called whenever a missing semicolon is inserted by the parser. The - callback will be given the character offset of the point where the - semicolon is inserted as argument, and if `locations` is on, also a - `{line, column}` object representing this position. - -- **onTrailingComma**: Like `onInsertedSemicolon`, but for trailing - commas. - -- **allowReserved**: If `false`, using a reserved word will generate - an error. Defaults to `true` for `ecmaVersion` 3, `false` for higher - versions. When given the value `"never"`, reserved words and - keywords can also not be used as property names (as in Internet - Explorer's old parser). - -- **allowReturnOutsideFunction**: By default, a return statement at - the top level raises an error. Set this to `true` to accept such - code. - -- **allowImportExportEverywhere**: By default, `import` and `export` - declarations can only appear at a program's top level. Setting this - option to `true` allows them anywhere where a statement is allowed. - -- **allowHashBang**: When this is enabled (off by default), if the - code starts with the characters `#!` (as in a shellscript), the - first line will be treated as a comment. - -- **locations**: When `true`, each node has a `loc` object attached - with `start` and `end` subobjects, each of which contains the - one-based line and zero-based column numbers in `{line, column}` - form. Default is `false`. - -- **onToken**: If a function is passed for this option, each found - token will be passed in same format as tokens returned from - `tokenizer().getToken()`. - - If array is passed, each found token is pushed to it. - - Note that you are not allowed to call the parser from the - callback—that will corrupt its internal state. - -- **onComment**: If a function is passed for this option, whenever a - comment is encountered the function will be called with the - following parameters: - - - `block`: `true` if the comment is a block comment, false if it - is a line comment. - - `text`: The content of the comment. - - `start`: Character offset of the start of the comment. - - `end`: Character offset of the end of the comment. - - When the `locations` options is on, the `{line, column}` locations - of the comment’s start and end are passed as two additional - parameters. - - If array is passed for this option, each found comment is pushed - to it as object in Esprima format: - - ```javascript - { - "type": "Line" | "Block", - "value": "comment text", - "start": Number, - "end": Number, - // If `locations` option is on: - "loc": { - "start": {line: Number, column: Number} - "end": {line: Number, column: Number} - }, - // If `ranges` option is on: - "range": [Number, Number] - } - ``` - - Note that you are not allowed to call the parser from the - callback—that will corrupt its internal state. - -- **ranges**: Nodes have their start and end characters offsets - recorded in `start` and `end` properties (directly on the node, - rather than the `loc` object, which holds line/column data. To also - add a [semi-standardized][range] `range` property holding a - `[start, end]` array with the same numbers, set the `ranges` option - to `true`. - -- **program**: It is possible to parse multiple files into a single - AST by passing the tree produced by parsing the first file as the - `program` option in subsequent parses. This will add the toplevel - forms of the parsed file to the "Program" (top) node of an existing - parse tree. - -- **sourceFile**: When the `locations` option is `true`, you can pass - this option to add a `source` attribute in every node’s `loc` - object. Note that the contents of this option are not examined or - processed in any way; you are free to use whatever format you - choose. - -- **directSourceFile**: Like `sourceFile`, but a `sourceFile` property - will be added directly to the nodes, rather than the `loc` object. - -- **preserveParens**: If this option is `true`, parenthesized expressions - are represented by (non-standard) `ParenthesizedExpression` nodes - that have a single `expression` property containing the expression - inside parentheses. - -[range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 - -**parseExpressionAt**`(input, offset, options)` will parse a single -expression in a string, and return its AST. It will not complain if -there is more of the string left after the expression. - -**getLineInfo**`(input, offset)` can be used to get a `{line, -column}` object for a given program string and character offset. - -**tokenizer**`(input, options)` returns an object with a `getToken` -method that can be called repeatedly to get the next token, a `{start, -end, type, value}` object (with added `loc` property when the -`locations` option is enabled and `range` property when the `ranges` -option is enabled). When the token's type is `tokTypes.eof`, you -should stop calling the method, since it will keep returning that same -token forever. - -In ES6 environment, returned result can be used as any other -protocol-compliant iterable: - -```javascript -for (let token of acorn.tokenizer(str)) { - // iterate over the tokens -} - -// transform code to array of tokens: -var tokens = [...acorn.tokenizer(str)]; -``` - -**tokTypes** holds an object mapping names to the token type objects -that end up in the `type` properties of tokens. - -#### Note on using with [Escodegen][escodegen] - -Escodegen supports generating comments from AST, attached in -Esprima-specific format. In order to simulate same format in -Acorn, consider following example: - -```javascript -var comments = [], tokens = []; - -var ast = acorn.parse('var x = 42; // answer', { - // collect ranges for each node - ranges: true, - // collect comments in Esprima's format - onComment: comments, - // collect token ranges - onToken: tokens -}); - -// attach comments using collected information -escodegen.attachComments(ast, comments, tokens); - -// generate code -console.log(escodegen.generate(ast, {comment: true})); -// > 'var x = 42; // answer' -``` - -[escodegen]: https://github.com/estools/escodegen - -### dist/acorn_loose.js ### - -This file implements an error-tolerant parser. It exposes a single -function. The loose parser is accessible in node.js via `require("acorn/dist/acorn_loose")`. - -**parse_dammit**`(input, options)` takes the same arguments and -returns the same syntax tree as the `parse` function in `acorn.js`, -but never raises an error, and will do its best to parse syntactically -invalid code in as meaningful a way as it can. It'll insert identifier -nodes with name `"✖"` as placeholders in places where it can't make -sense of the input. Depends on `acorn.js`, because it uses the same -tokenizer. - -### dist/walk.js ### - -Implements an abstract syntax tree walker. Will store its interface in -`acorn.walk` when loaded without a module system. - -**simple**`(node, visitors, base, state)` does a 'simple' walk over -a tree. `node` should be the AST node to walk, and `visitors` an -object with properties whose names correspond to node types in the -[ESTree spec][estree]. The properties should contain functions -that will be called with the node object and, if applicable the state -at that point. The last two arguments are optional. `base` is a walker -algorithm, and `state` is a start state. The default walker will -simply visit all statements and expressions and not produce a -meaningful state. (An example of a use of state is to track scope at -each point in the tree.) - -**ancestor**`(node, visitors, base, state)` does a 'simple' walk over -a tree, building up an array of ancestor nodes (including the current node) -and passing the array to callbacks in the `state` parameter. - -**recursive**`(node, state, functions, base)` does a 'recursive' -walk, where the walker functions are responsible for continuing the -walk on the child nodes of their target node. `state` is the start -state, and `functions` should contain an object that maps node types -to walker functions. Such functions are called with `(node, state, c)` -arguments, and can cause the walk to continue on a sub-node by calling -the `c` argument on it with `(node, state)` arguments. The optional -`base` argument provides the fallback walker functions for node types -that aren't handled in the `functions` object. If not given, the -default walkers will be used. - -**make**`(functions, base)` builds a new walker object by using the -walker functions in `functions` and filling in the missing ones by -taking defaults from `base`. - -**findNodeAt**`(node, start, end, test, base, state)` tries to -locate a node in a tree at the given start and/or end offsets, which -satisfies the predicate `test`. `start` and `end` can be either `null` -(as wildcard) or a number. `test` may be a string (indicating a node -type) or a function that takes `(nodeType, node)` arguments and -returns a boolean indicating whether this node is interesting. `base` -and `state` are optional, and can be used to specify a custom walker. -Nodes are tested from inner to outer, so if two nodes match the -boundaries, the inner one will be preferred. - -**findNodeAround**`(node, pos, test, base, state)` is a lot like -`findNodeAt`, but will match any node that exists 'around' (spanning) -the given position. - -**findNodeAfter**`(node, pos, test, base, state)` is similar to -`findNodeAround`, but will match all nodes *after* the given position -(testing outer nodes before inner nodes). - -## Command line interface - -The `bin/acorn` utility can be used to parse a file from the command -line. It accepts as arguments its input file and the following -options: - -- `--ecma3|--ecma5|--ecma6`: Sets the ECMAScript version to parse. Default is - version 5. - -- `--module`: Sets the parsing mode to `"module"`. Is set to `"script"` otherwise. - -- `--locations`: Attaches a "loc" object to each node with "start" and - "end" subobjects, each of which contains the one-based line and - zero-based column numbers in `{line, column}` form. - -- `--allow-hash-bang`: If the code starts with the characters #! (as in a shellscript), the first line will be treated as a comment. - -- `--compact`: No whitespace is used in the AST output. - -- `--silent`: Do not output the AST, just return the exit status. - -- `--help`: Print the usage information and quit. - -The utility spits out the syntax tree as JSON data. - -## Build system - -Acorn is written in ECMAScript 6, as a set of small modules, in the -project's `src` directory, and compiled down to bigger ECMAScript 3 -files in `dist` using [Browserify](http://browserify.org) and -[Babel](http://babeljs.io/). If you are already using Babel, you can -consider including the modules directly. - -The command-line test runner (`npm test`) uses the ES6 modules. The -browser-based test page (`test/index.html`) uses the compiled modules. -The `bin/build-acorn.js` script builds the latter from the former. - -If you are working on Acorn, you'll probably want to try the code out -directly, without an intermediate build step. In your scripts, you can -register the Babel require shim like this: - - require("babel-core/register") - -That will allow you to directly `require` the ES6 modules. - -## Plugins - -Acorn is designed support allow plugins which, within reasonable -bounds, redefine the way the parser works. Plugins can add new token -types and new tokenizer contexts (if necessary), and extend methods in -the parser object. This is not a clean, elegant API—using it requires -an understanding of Acorn's internals, and plugins are likely to break -whenever those internals are significantly changed. But still, it is -_possible_, in this way, to create parsers for JavaScript dialects -without forking all of Acorn. And in principle it is even possible to -combine such plugins, so that if you have, for example, a plugin for -parsing types and a plugin for parsing JSX-style XML literals, you -could load them both and parse code with both JSX tags and types. - -A plugin should register itself by adding a property to -`acorn.plugins`, which holds a function. Calling `acorn.parse`, a -`plugins` option can be passed, holding an object mapping plugin names -to configuration values (or just `true` for plugins that don't take -options). After the parser object has been created, the initialization -functions for the chosen plugins are called with `(parser, -configValue)` arguments. They are expected to use the `parser.extend` -method to extend parser methods. For example, the `readToken` method -could be extended like this: - -```javascript -parser.extend("readToken", function(nextMethod) { - return function(code) { - console.log("Reading a token!") - return nextMethod.call(this, code) - } -}) -``` - -The `nextMethod` argument passed to `extend`'s second argument is the -previous value of this method, and should usually be called through to -whenever the extended method does not handle the call itself. - -Similarly, the loose parser allows plugins to register themselves via -`acorn.pluginsLoose`. The extension mechanism is the same as for the -normal parser: - -```javascript -looseParser.extend("readToken", function(nextMethod) { - return function() { - console.log("Reading a token in the loose parser!") - return nextMethod.call(this) - } -}) -``` - -There is a proof-of-concept JSX plugin in the [`acorn-jsx`](https://github.com/RReverser/acorn-jsx) project. diff --git a/web/node_modules/acorn/bin/acorn b/web/node_modules/acorn/bin/acorn deleted file mode 100755 index db07909..0000000 --- a/web/node_modules/acorn/bin/acorn +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env node -"use strict"; - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj["default"] = obj; return newObj; } } - -var _path = require("path"); - -var _fs = require("fs"); - -var _distAcornJs = require("../dist/acorn.js"); - -var acorn = _interopRequireWildcard(_distAcornJs); - -var infile = undefined, - forceFile = undefined, - silent = false, - compact = false, - tokenize = false; -var options = {}; - -function help(status) { - var print = status == 0 ? console.log : console.error; - print("usage: " + (0, _path.basename)(process.argv[1]) + " [--ecma3|--ecma5|--ecma6]"); - print(" [--tokenize] [--locations] [---allow-hash-bang] [--compact] [--silent] [--module] [--help] [--] [infile]"); - process.exit(status); -} - -for (var i = 2; i < process.argv.length; ++i) { - var arg = process.argv[i]; - if ((arg == "-" || arg[0] != "-") && !infile) infile = arg;else if (arg == "--" && !infile && i + 2 == process.argv.length) forceFile = infile = process.argv[++i];else if (arg == "--ecma3") options.ecmaVersion = 3;else if (arg == "--ecma5") options.ecmaVersion = 5;else if (arg == "--ecma6") options.ecmaVersion = 6;else if (arg == "--locations") options.locations = true;else if (arg == "--allow-hash-bang") options.allowHashBang = true;else if (arg == "--silent") silent = true;else if (arg == "--compact") compact = true;else if (arg == "--help") help(0);else if (arg == "--tokenize") tokenize = true;else if (arg == "--module") options.sourceType = 'module';else help(1); -} - -function run(code) { - var result = undefined; - if (!tokenize) { - try { - result = acorn.parse(code, options); - } catch (e) { - console.error(e.message);process.exit(1); - } - } else { - result = []; - var tokenizer = acorn.tokenizer(code, options), - token = undefined; - while (true) { - try { - token = tokenizer.getToken(); - } catch (e) { - console.error(e.message);process.exit(1); - } - result.push(token); - if (token.type == acorn.tokTypes.eof) break; - } - } - if (!silent) console.log(JSON.stringify(result, null, compact ? null : 2)); -} - -if (forceFile || infile && infile != "-") { - run((0, _fs.readFileSync)(infile, "utf8")); -} else { - (function () { - var code = ""; - process.stdin.resume(); - process.stdin.on("data", function (chunk) { - return code += chunk; - }); - process.stdin.on("end", function () { - return run(code); - }); - })(); -} \ No newline at end of file diff --git a/web/node_modules/acorn/bin/build-acorn.js b/web/node_modules/acorn/bin/build-acorn.js deleted file mode 100644 index 71f2cf9..0000000 --- a/web/node_modules/acorn/bin/build-acorn.js +++ /dev/null @@ -1,82 +0,0 @@ -var fs = require("fs"), path = require("path") -var stream = require("stream") - -var browserify = require("browserify") -var babel = require('babel-core') -var babelify = require("babelify").configure({loose: "all"}) - -process.chdir(path.resolve(__dirname, "..")) - -browserify({standalone: "acorn"}) - .plugin(require('browserify-derequire')) - .transform(babelify) - .require("./src/index.js", {entry: true}) - .bundle() - .on("error", function (err) { console.log("Error: " + err.message) }) - .pipe(fs.createWriteStream("dist/acorn.js")) - -var ACORN_PLACEHOLDER = "this_function_call_should_be_replaced_with_a_call_to_load_acorn()"; -function acornShimPrepare(file) { - var tr = new stream.Transform - if (file == path.resolve(__dirname, "../src/index.js")) { - var sent = false - tr._transform = function(chunk, _, callback) { - if (!sent) { - sent = true - callback(null, ACORN_PLACEHOLDER); - } else { - callback() - } - } - } else { - tr._transform = function(chunk, _, callback) { callback(null, chunk) } - } - return tr -} -function acornShimComplete() { - var tr = new stream.Transform - var buffer = ""; - tr._transform = function(chunk, _, callback) { - buffer += chunk.toString("utf8"); - callback(); - }; - tr._flush = function (callback) { - tr.push(buffer.replace(ACORN_PLACEHOLDER, "module.exports = typeof acorn != 'undefined' ? acorn : require(\"./acorn\")")); - callback(null); - }; - return tr; -} - -browserify({standalone: "acorn.loose"}) - .plugin(require('browserify-derequire')) - .transform(acornShimPrepare) - .transform(babelify) - .require("./src/loose/index.js", {entry: true}) - .bundle() - .on("error", function (err) { console.log("Error: " + err.message) }) - .pipe(acornShimComplete()) - .pipe(fs.createWriteStream("dist/acorn_loose.js")) - -browserify({standalone: "acorn.walk"}) - .plugin(require('browserify-derequire')) - .transform(acornShimPrepare) - .transform(babelify) - .require("./src/walk/index.js", {entry: true}) - .bundle() - .on("error", function (err) { console.log("Error: " + err.message) }) - .pipe(acornShimComplete()) - .pipe(fs.createWriteStream("dist/walk.js")) - -babel.transformFile("./src/bin/acorn.js", function (err, result) { - if (err) return console.log("Error: " + err.message) - fs.writeFile("bin/acorn", result.code, function (err) { - if (err) return console.log("Error: " + err.message) - - // Make bin/acorn executable - if (process.platform === 'win32') - return - var stat = fs.statSync("bin/acorn") - var newPerm = stat.mode | parseInt('111', 8) - fs.chmodSync("bin/acorn", newPerm) - }) -}) diff --git a/web/node_modules/acorn/bin/generate-identifier-regex.js b/web/node_modules/acorn/bin/generate-identifier-regex.js deleted file mode 100644 index 0d7c50f..0000000 --- a/web/node_modules/acorn/bin/generate-identifier-regex.js +++ /dev/null @@ -1,47 +0,0 @@ -// Note: run `npm install unicode-7.0.0` first. - -// Which Unicode version should be used? -var version = '7.0.0'; - -var start = require('unicode-' + version + '/properties/ID_Start/code-points') - .filter(function(ch) { return ch > 127; }); -var cont = [0x200c, 0x200d].concat(require('unicode-' + version + '/properties/ID_Continue/code-points') - .filter(function(ch) { return ch > 127 && start.indexOf(ch) == -1; })); - -function pad(str, width) { - while (str.length < width) str = "0" + str; - return str; -} - -function esc(code) { - var hex = code.toString(16); - if (hex.length <= 2) return "\\x" + pad(hex, 2); - else return "\\u" + pad(hex, 4); -} - -function generate(chars) { - var astral = [], re = ""; - for (var i = 0, at = 0x10000; i < chars.length; i++) { - var from = chars[i], to = from; - while (i < chars.length - 1 && chars[i + 1] == to + 1) { - i++; - to++; - } - if (to <= 0xffff) { - if (from == to) re += esc(from); - else if (from + 1 == to) re += esc(from) + esc(to); - else re += esc(from) + "-" + esc(to); - } else { - astral.push(from - at, to - from); - at = to; - } - } - return {nonASCII: re, astral: astral}; -} - -var startData = generate(start), contData = generate(cont); - -console.log(" var nonASCIIidentifierStartChars = \"" + startData.nonASCII + "\";"); -console.log(" var nonASCIIidentifierChars = \"" + contData.nonASCII + "\";"); -console.log(" var astralIdentifierStartCodes = " + JSON.stringify(startData.astral) + ";"); -console.log(" var astralIdentifierCodes = " + JSON.stringify(contData.astral) + ";"); diff --git a/web/node_modules/acorn/bin/update_authors.sh b/web/node_modules/acorn/bin/update_authors.sh deleted file mode 100755 index 466c8db..0000000 --- a/web/node_modules/acorn/bin/update_authors.sh +++ /dev/null @@ -1,6 +0,0 @@ -# Combine existing list of authors with everyone known in git, sort, add header. -tail --lines=+3 AUTHORS > AUTHORS.tmp -git log --format='%aN' | grep -v abraidwood >> AUTHORS.tmp -echo -e "List of Acorn contributors. Updated before every release.\n" > AUTHORS -sort -u AUTHORS.tmp >> AUTHORS -rm -f AUTHORS.tmp diff --git a/web/node_modules/acorn/dist/.keep b/web/node_modules/acorn/dist/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/web/node_modules/acorn/dist/acorn.js b/web/node_modules/acorn/dist/acorn.js deleted file mode 100644 index 9419f86..0000000 --- a/web/node_modules/acorn/dist/acorn.js +++ /dev/null @@ -1,3340 +0,0 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.acorn = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 6 && (prop.computed || prop.method || prop.shorthand)) return; - var key = prop.key;var name = undefined; - switch (key.type) { - case "Identifier": - name = key.name;break; - case "Literal": - name = String(key.value);break; - default: - return; - } - var kind = prop.kind; - - if (this.options.ecmaVersion >= 6) { - if (name === "__proto__" && kind === "init") { - if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property"); - propHash.proto = true; - } - return; - } - name = "$" + name; - var other = propHash[name]; - if (other) { - var isGetSet = kind !== "init"; - if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init)) this.raise(key.start, "Redefinition of property"); - } else { - other = propHash[name] = { - init: false, - get: false, - set: false - }; - } - other[kind] = true; -}; - -// ### Expression parsing - -// These nest, from the most general expression type at the top to -// 'atomic', nondivisible expression types at the bottom. Most of -// the functions will simply let the function(s) below them parse, -// and, *if* the syntactic construct they handle is present, wrap -// the AST node that the inner parser gave them in another node. - -// Parse a full expression. The optional arguments are used to -// forbid the `in` operator (in for loops initalization expressions) -// and provide reference for storing '=' operator inside shorthand -// property assignment in contexts where both object expression -// and object pattern might appear (so it's possible to raise -// delayed syntax error at correct position). - -pp.parseExpression = function (noIn, refDestructuringErrors) { - var startPos = this.start, - startLoc = this.startLoc; - var expr = this.parseMaybeAssign(noIn, refDestructuringErrors); - if (this.type === _tokentype.types.comma) { - var node = this.startNodeAt(startPos, startLoc); - node.expressions = [expr]; - while (this.eat(_tokentype.types.comma)) node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors)); - return this.finishNode(node, "SequenceExpression"); - } - return expr; -}; - -// Parse an assignment expression. This includes applications of -// operators like `+=`. - -pp.parseMaybeAssign = function (noIn, refDestructuringErrors, afterLeftParse) { - if (this.type == _tokentype.types._yield && this.inGenerator) return this.parseYield(); - - var validateDestructuring = false; - if (!refDestructuringErrors) { - refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 }; - validateDestructuring = true; - } - var startPos = this.start, - startLoc = this.startLoc; - if (this.type == _tokentype.types.parenL || this.type == _tokentype.types.name) this.potentialArrowAt = this.start; - var left = this.parseMaybeConditional(noIn, refDestructuringErrors); - if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc); - if (this.type.isAssign) { - if (validateDestructuring) this.checkPatternErrors(refDestructuringErrors, true); - var node = this.startNodeAt(startPos, startLoc); - node.operator = this.value; - node.left = this.type === _tokentype.types.eq ? this.toAssignable(left) : left; - refDestructuringErrors.shorthandAssign = 0; // reset because shorthand default was used correctly - this.checkLVal(left); - this.next(); - node.right = this.parseMaybeAssign(noIn); - return this.finishNode(node, "AssignmentExpression"); - } else { - if (validateDestructuring) this.checkExpressionErrors(refDestructuringErrors, true); - } - return left; -}; - -// Parse a ternary conditional (`?:`) operator. - -pp.parseMaybeConditional = function (noIn, refDestructuringErrors) { - var startPos = this.start, - startLoc = this.startLoc; - var expr = this.parseExprOps(noIn, refDestructuringErrors); - if (this.checkExpressionErrors(refDestructuringErrors)) return expr; - if (this.eat(_tokentype.types.question)) { - var node = this.startNodeAt(startPos, startLoc); - node.test = expr; - node.consequent = this.parseMaybeAssign(); - this.expect(_tokentype.types.colon); - node.alternate = this.parseMaybeAssign(noIn); - return this.finishNode(node, "ConditionalExpression"); - } - return expr; -}; - -// Start the precedence parser. - -pp.parseExprOps = function (noIn, refDestructuringErrors) { - var startPos = this.start, - startLoc = this.startLoc; - var expr = this.parseMaybeUnary(refDestructuringErrors); - if (this.checkExpressionErrors(refDestructuringErrors)) return expr; - return this.parseExprOp(expr, startPos, startLoc, -1, noIn); -}; - -// Parse binary operators with the operator precedence parsing -// algorithm. `left` is the left-hand side of the operator. -// `minPrec` provides context that allows the function to stop and -// defer further parser to one of its callers when it encounters an -// operator that has a lower precedence than the set it is parsing. - -pp.parseExprOp = function (left, leftStartPos, leftStartLoc, minPrec, noIn) { - var prec = this.type.binop; - if (prec != null && (!noIn || this.type !== _tokentype.types._in)) { - if (prec > minPrec) { - var node = this.startNodeAt(leftStartPos, leftStartLoc); - node.left = left; - node.operator = this.value; - var op = this.type; - this.next(); - var startPos = this.start, - startLoc = this.startLoc; - node.right = this.parseExprOp(this.parseMaybeUnary(), startPos, startLoc, prec, noIn); - this.finishNode(node, op === _tokentype.types.logicalOR || op === _tokentype.types.logicalAND ? "LogicalExpression" : "BinaryExpression"); - return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn); - } - } - return left; -}; - -// Parse unary operators, both prefix and postfix. - -pp.parseMaybeUnary = function (refDestructuringErrors) { - if (this.type.prefix) { - var node = this.startNode(), - update = this.type === _tokentype.types.incDec; - node.operator = this.value; - node.prefix = true; - this.next(); - node.argument = this.parseMaybeUnary(); - this.checkExpressionErrors(refDestructuringErrors, true); - if (update) this.checkLVal(node.argument);else if (this.strict && node.operator === "delete" && node.argument.type === "Identifier") this.raise(node.start, "Deleting local variable in strict mode"); - return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); - } - var startPos = this.start, - startLoc = this.startLoc; - var expr = this.parseExprSubscripts(refDestructuringErrors); - if (this.checkExpressionErrors(refDestructuringErrors)) return expr; - while (this.type.postfix && !this.canInsertSemicolon()) { - var node = this.startNodeAt(startPos, startLoc); - node.operator = this.value; - node.prefix = false; - node.argument = expr; - this.checkLVal(expr); - this.next(); - expr = this.finishNode(node, "UpdateExpression"); - } - return expr; -}; - -// Parse call, dot, and `[]`-subscript expressions. - -pp.parseExprSubscripts = function (refDestructuringErrors) { - var startPos = this.start, - startLoc = this.startLoc; - var expr = this.parseExprAtom(refDestructuringErrors); - var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"; - if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) return expr; - return this.parseSubscripts(expr, startPos, startLoc); -}; - -pp.parseSubscripts = function (base, startPos, startLoc, noCalls) { - for (;;) { - if (this.eat(_tokentype.types.dot)) { - var node = this.startNodeAt(startPos, startLoc); - node.object = base; - node.property = this.parseIdent(true); - node.computed = false; - base = this.finishNode(node, "MemberExpression"); - } else if (this.eat(_tokentype.types.bracketL)) { - var node = this.startNodeAt(startPos, startLoc); - node.object = base; - node.property = this.parseExpression(); - node.computed = true; - this.expect(_tokentype.types.bracketR); - base = this.finishNode(node, "MemberExpression"); - } else if (!noCalls && this.eat(_tokentype.types.parenL)) { - var node = this.startNodeAt(startPos, startLoc); - node.callee = base; - node.arguments = this.parseExprList(_tokentype.types.parenR, false); - base = this.finishNode(node, "CallExpression"); - } else if (this.type === _tokentype.types.backQuote) { - var node = this.startNodeAt(startPos, startLoc); - node.tag = base; - node.quasi = this.parseTemplate(); - base = this.finishNode(node, "TaggedTemplateExpression"); - } else { - return base; - } - } -}; - -// Parse an atomic expression — either a single token that is an -// expression, an expression started by a keyword like `function` or -// `new`, or an expression wrapped in punctuation like `()`, `[]`, -// or `{}`. - -pp.parseExprAtom = function (refDestructuringErrors) { - var node = undefined, - canBeArrow = this.potentialArrowAt == this.start; - switch (this.type) { - case _tokentype.types._super: - if (!this.inFunction) this.raise(this.start, "'super' outside of function or class"); - case _tokentype.types._this: - var type = this.type === _tokentype.types._this ? "ThisExpression" : "Super"; - node = this.startNode(); - this.next(); - return this.finishNode(node, type); - - case _tokentype.types._yield: - if (this.inGenerator) this.unexpected(); - - case _tokentype.types.name: - var startPos = this.start, - startLoc = this.startLoc; - var id = this.parseIdent(this.type !== _tokentype.types.name); - if (canBeArrow && !this.canInsertSemicolon() && this.eat(_tokentype.types.arrow)) return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id]); - return id; - - case _tokentype.types.regexp: - var value = this.value; - node = this.parseLiteral(value.value); - node.regex = { pattern: value.pattern, flags: value.flags }; - return node; - - case _tokentype.types.num:case _tokentype.types.string: - return this.parseLiteral(this.value); - - case _tokentype.types._null:case _tokentype.types._true:case _tokentype.types._false: - node = this.startNode(); - node.value = this.type === _tokentype.types._null ? null : this.type === _tokentype.types._true; - node.raw = this.type.keyword; - this.next(); - return this.finishNode(node, "Literal"); - - case _tokentype.types.parenL: - return this.parseParenAndDistinguishExpression(canBeArrow); - - case _tokentype.types.bracketL: - node = this.startNode(); - this.next(); - // check whether this is array comprehension or regular array - if (this.options.ecmaVersion >= 7 && this.type === _tokentype.types._for) { - return this.parseComprehension(node, false); - } - node.elements = this.parseExprList(_tokentype.types.bracketR, true, true, refDestructuringErrors); - return this.finishNode(node, "ArrayExpression"); - - case _tokentype.types.braceL: - return this.parseObj(false, refDestructuringErrors); - - case _tokentype.types._function: - node = this.startNode(); - this.next(); - return this.parseFunction(node, false); - - case _tokentype.types._class: - return this.parseClass(this.startNode(), false); - - case _tokentype.types._new: - return this.parseNew(); - - case _tokentype.types.backQuote: - return this.parseTemplate(); - - default: - this.unexpected(); - } -}; - -pp.parseLiteral = function (value) { - var node = this.startNode(); - node.value = value; - node.raw = this.input.slice(this.start, this.end); - this.next(); - return this.finishNode(node, "Literal"); -}; - -pp.parseParenExpression = function () { - this.expect(_tokentype.types.parenL); - var val = this.parseExpression(); - this.expect(_tokentype.types.parenR); - return val; -}; - -pp.parseParenAndDistinguishExpression = function (canBeArrow) { - var startPos = this.start, - startLoc = this.startLoc, - val = undefined; - if (this.options.ecmaVersion >= 6) { - this.next(); - - if (this.options.ecmaVersion >= 7 && this.type === _tokentype.types._for) { - return this.parseComprehension(this.startNodeAt(startPos, startLoc), true); - } - - var innerStartPos = this.start, - innerStartLoc = this.startLoc; - var exprList = [], - first = true; - var refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 }, - spreadStart = undefined, - innerParenStart = undefined; - while (this.type !== _tokentype.types.parenR) { - first ? first = false : this.expect(_tokentype.types.comma); - if (this.type === _tokentype.types.ellipsis) { - spreadStart = this.start; - exprList.push(this.parseParenItem(this.parseRest())); - break; - } else { - if (this.type === _tokentype.types.parenL && !innerParenStart) { - innerParenStart = this.start; - } - exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)); - } - } - var innerEndPos = this.start, - innerEndLoc = this.startLoc; - this.expect(_tokentype.types.parenR); - - if (canBeArrow && !this.canInsertSemicolon() && this.eat(_tokentype.types.arrow)) { - this.checkPatternErrors(refDestructuringErrors, true); - if (innerParenStart) this.unexpected(innerParenStart); - return this.parseParenArrowList(startPos, startLoc, exprList); - } - - if (!exprList.length) this.unexpected(this.lastTokStart); - if (spreadStart) this.unexpected(spreadStart); - this.checkExpressionErrors(refDestructuringErrors, true); - - if (exprList.length > 1) { - val = this.startNodeAt(innerStartPos, innerStartLoc); - val.expressions = exprList; - this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); - } else { - val = exprList[0]; - } - } else { - val = this.parseParenExpression(); - } - - if (this.options.preserveParens) { - var par = this.startNodeAt(startPos, startLoc); - par.expression = val; - return this.finishNode(par, "ParenthesizedExpression"); - } else { - return val; - } -}; - -pp.parseParenItem = function (item) { - return item; -}; - -pp.parseParenArrowList = function (startPos, startLoc, exprList) { - return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList); -}; - -// New's precedence is slightly tricky. It must allow its argument to -// be a `[]` or dot subscript expression, but not a call — at least, -// not without wrapping it in parentheses. Thus, it uses the noCalls -// argument to parseSubscripts to prevent it from consuming the -// argument list. - -var empty = []; - -pp.parseNew = function () { - var node = this.startNode(); - var meta = this.parseIdent(true); - if (this.options.ecmaVersion >= 6 && this.eat(_tokentype.types.dot)) { - node.meta = meta; - node.property = this.parseIdent(true); - if (node.property.name !== "target") this.raise(node.property.start, "The only valid meta property for new is new.target"); - if (!this.inFunction) this.raise(node.start, "new.target can only be used in functions"); - return this.finishNode(node, "MetaProperty"); - } - var startPos = this.start, - startLoc = this.startLoc; - node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true); - if (this.eat(_tokentype.types.parenL)) node.arguments = this.parseExprList(_tokentype.types.parenR, false);else node.arguments = empty; - return this.finishNode(node, "NewExpression"); -}; - -// Parse template expression. - -pp.parseTemplateElement = function () { - var elem = this.startNode(); - elem.value = { - raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, '\n'), - cooked: this.value - }; - this.next(); - elem.tail = this.type === _tokentype.types.backQuote; - return this.finishNode(elem, "TemplateElement"); -}; - -pp.parseTemplate = function () { - var node = this.startNode(); - this.next(); - node.expressions = []; - var curElt = this.parseTemplateElement(); - node.quasis = [curElt]; - while (!curElt.tail) { - this.expect(_tokentype.types.dollarBraceL); - node.expressions.push(this.parseExpression()); - this.expect(_tokentype.types.braceR); - node.quasis.push(curElt = this.parseTemplateElement()); - } - this.next(); - return this.finishNode(node, "TemplateLiteral"); -}; - -// Parse an object literal or binding pattern. - -pp.parseObj = function (isPattern, refDestructuringErrors) { - var node = this.startNode(), - first = true, - propHash = {}; - node.properties = []; - this.next(); - while (!this.eat(_tokentype.types.braceR)) { - if (!first) { - this.expect(_tokentype.types.comma); - if (this.afterTrailingComma(_tokentype.types.braceR)) break; - } else first = false; - - var prop = this.startNode(), - isGenerator = undefined, - startPos = undefined, - startLoc = undefined; - if (this.options.ecmaVersion >= 6) { - prop.method = false; - prop.shorthand = false; - if (isPattern || refDestructuringErrors) { - startPos = this.start; - startLoc = this.startLoc; - } - if (!isPattern) isGenerator = this.eat(_tokentype.types.star); - } - this.parsePropertyName(prop); - this.parsePropertyValue(prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors); - this.checkPropClash(prop, propHash); - node.properties.push(this.finishNode(prop, "Property")); - } - return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression"); -}; - -pp.parsePropertyValue = function (prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors) { - if (this.eat(_tokentype.types.colon)) { - prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); - prop.kind = "init"; - } else if (this.options.ecmaVersion >= 6 && this.type === _tokentype.types.parenL) { - if (isPattern) this.unexpected(); - prop.kind = "init"; - prop.method = true; - prop.value = this.parseMethod(isGenerator); - } else if (this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set") && (this.type != _tokentype.types.comma && this.type != _tokentype.types.braceR)) { - if (isGenerator || isPattern) this.unexpected(); - prop.kind = prop.key.name; - this.parsePropertyName(prop); - prop.value = this.parseMethod(false); - var paramCount = prop.kind === "get" ? 0 : 1; - if (prop.value.params.length !== paramCount) { - var start = prop.value.start; - if (prop.kind === "get") this.raise(start, "getter should have no params");else this.raise(start, "setter should have exactly one param"); - } - if (prop.kind === "set" && prop.value.params[0].type === "RestElement") this.raise(prop.value.params[0].start, "Setter cannot use rest params"); - } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { - prop.kind = "init"; - if (isPattern) { - if (this.keywords.test(prop.key.name) || (this.strict ? this.reservedWordsStrictBind : this.reservedWords).test(prop.key.name)) this.raise(prop.key.start, "Binding " + prop.key.name); - prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); - } else if (this.type === _tokentype.types.eq && refDestructuringErrors) { - if (!refDestructuringErrors.shorthandAssign) refDestructuringErrors.shorthandAssign = this.start; - prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); - } else { - prop.value = prop.key; - } - prop.shorthand = true; - } else this.unexpected(); -}; - -pp.parsePropertyName = function (prop) { - if (this.options.ecmaVersion >= 6) { - if (this.eat(_tokentype.types.bracketL)) { - prop.computed = true; - prop.key = this.parseMaybeAssign(); - this.expect(_tokentype.types.bracketR); - return prop.key; - } else { - prop.computed = false; - } - } - return prop.key = this.type === _tokentype.types.num || this.type === _tokentype.types.string ? this.parseExprAtom() : this.parseIdent(true); -}; - -// Initialize empty function node. - -pp.initFunction = function (node) { - node.id = null; - if (this.options.ecmaVersion >= 6) { - node.generator = false; - node.expression = false; - } -}; - -// Parse object or class method. - -pp.parseMethod = function (isGenerator) { - var node = this.startNode(); - this.initFunction(node); - this.expect(_tokentype.types.parenL); - node.params = this.parseBindingList(_tokentype.types.parenR, false, false); - if (this.options.ecmaVersion >= 6) node.generator = isGenerator; - this.parseFunctionBody(node, false); - return this.finishNode(node, "FunctionExpression"); -}; - -// Parse arrow function expression with given parameters. - -pp.parseArrowExpression = function (node, params) { - this.initFunction(node); - node.params = this.toAssignableList(params, true); - this.parseFunctionBody(node, true); - return this.finishNode(node, "ArrowFunctionExpression"); -}; - -// Parse function body and check parameters. - -pp.parseFunctionBody = function (node, isArrowFunction) { - var isExpression = isArrowFunction && this.type !== _tokentype.types.braceL; - - if (isExpression) { - node.body = this.parseMaybeAssign(); - node.expression = true; - } else { - // Start a new scope with regard to labels and the `inFunction` - // flag (restore them to their old value afterwards). - var oldInFunc = this.inFunction, - oldInGen = this.inGenerator, - oldLabels = this.labels; - this.inFunction = true;this.inGenerator = node.generator;this.labels = []; - node.body = this.parseBlock(true); - node.expression = false; - this.inFunction = oldInFunc;this.inGenerator = oldInGen;this.labels = oldLabels; - } - - // If this is a strict mode function, verify that argument names - // are not repeated, and it does not try to bind the words `eval` - // or `arguments`. - if (this.strict || !isExpression && node.body.body.length && this.isUseStrict(node.body.body[0])) { - var oldStrict = this.strict; - this.strict = true; - if (node.id) this.checkLVal(node.id, true); - this.checkParams(node); - this.strict = oldStrict; - } else if (isArrowFunction) { - this.checkParams(node); - } -}; - -// Checks function params for various disallowed patterns such as using "eval" -// or "arguments" and duplicate parameters. - -pp.checkParams = function (node) { - var nameHash = {}; - for (var i = 0; i < node.params.length; i++) { - this.checkLVal(node.params[i], true, nameHash); - } -}; - -// Parses a comma-separated list of expressions, and returns them as -// an array. `close` is the token type that ends the list, and -// `allowEmpty` can be turned on to allow subsequent commas with -// nothing in between them to be parsed as `null` (which is needed -// for array literals). - -pp.parseExprList = function (close, allowTrailingComma, allowEmpty, refDestructuringErrors) { - var elts = [], - first = true; - while (!this.eat(close)) { - if (!first) { - this.expect(_tokentype.types.comma); - if (this.type === close && refDestructuringErrors && !refDestructuringErrors.trailingComma) { - refDestructuringErrors.trailingComma = this.lastTokStart; - } - if (allowTrailingComma && this.afterTrailingComma(close)) break; - } else first = false; - - var elt = undefined; - if (allowEmpty && this.type === _tokentype.types.comma) elt = null;else if (this.type === _tokentype.types.ellipsis) elt = this.parseSpread(refDestructuringErrors);else elt = this.parseMaybeAssign(false, refDestructuringErrors); - elts.push(elt); - } - return elts; -}; - -// Parse the next token as an identifier. If `liberal` is true (used -// when parsing properties), it will also convert keywords into -// identifiers. - -pp.parseIdent = function (liberal) { - var node = this.startNode(); - if (liberal && this.options.allowReserved == "never") liberal = false; - if (this.type === _tokentype.types.name) { - if (!liberal && (this.strict ? this.reservedWordsStrict : this.reservedWords).test(this.value) && (this.options.ecmaVersion >= 6 || this.input.slice(this.start, this.end).indexOf("\\") == -1)) this.raise(this.start, "The keyword '" + this.value + "' is reserved"); - node.name = this.value; - } else if (liberal && this.type.keyword) { - node.name = this.type.keyword; - } else { - this.unexpected(); - } - this.next(); - return this.finishNode(node, "Identifier"); -}; - -// Parses yield expression inside generator. - -pp.parseYield = function () { - var node = this.startNode(); - this.next(); - if (this.type == _tokentype.types.semi || this.canInsertSemicolon() || this.type != _tokentype.types.star && !this.type.startsExpr) { - node.delegate = false; - node.argument = null; - } else { - node.delegate = this.eat(_tokentype.types.star); - node.argument = this.parseMaybeAssign(); - } - return this.finishNode(node, "YieldExpression"); -}; - -// Parses array and generator comprehensions. - -pp.parseComprehension = function (node, isGenerator) { - node.blocks = []; - while (this.type === _tokentype.types._for) { - var block = this.startNode(); - this.next(); - this.expect(_tokentype.types.parenL); - block.left = this.parseBindingAtom(); - this.checkLVal(block.left, true); - this.expectContextual("of"); - block.right = this.parseExpression(); - this.expect(_tokentype.types.parenR); - node.blocks.push(this.finishNode(block, "ComprehensionBlock")); - } - node.filter = this.eat(_tokentype.types._if) ? this.parseParenExpression() : null; - node.body = this.parseExpression(); - this.expect(isGenerator ? _tokentype.types.parenR : _tokentype.types.bracketR); - node.generator = isGenerator; - return this.finishNode(node, "ComprehensionExpression"); -}; - -},{"./state":10,"./tokentype":14}],2:[function(_dereq_,module,exports){ -// This is a trick taken from Esprima. It turns out that, on -// non-Chrome browsers, to check whether a string is in a set, a -// predicate containing a big ugly `switch` statement is faster than -// a regular expression, and on Chrome the two are about on par. -// This function uses `eval` (non-lexical) to produce such a -// predicate from a space-separated string of words. -// -// It starts by sorting the words by length. - -// Reserved word lists for various dialects of the language - -"use strict"; - -exports.__esModule = true; -exports.isIdentifierStart = isIdentifierStart; -exports.isIdentifierChar = isIdentifierChar; -var reservedWords = { - 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", - 5: "class enum extends super const export import", - 6: "enum", - strict: "implements interface let package private protected public static yield", - strictBind: "eval arguments" -}; - -exports.reservedWords = reservedWords; -// And the keywords - -var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; - -var keywords = { - 5: ecma5AndLessKeywords, - 6: ecma5AndLessKeywords + " let const class extends export import yield super" -}; - -exports.keywords = keywords; -// ## Character categories - -// Big ugly regular expressions that match characters in the -// whitespace, identifier, and identifier-start categories. These -// are only applied when a character is found to actually have a -// code point above 128. -// Generated by `bin/generate-identifier-regex.js`. - -var nonASCIIidentifierStartChars = "ªµºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮͰ-ʹͶͷͺ-ͽͿΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙա-ևא-תװ-ײؠ-يٮٯٱ-ۓەۥۦۮۯۺ-ۼۿܐܒ-ܯݍ-ޥޱߊ-ߪߴߵߺࠀ-ࠕࠚࠤࠨࡀ-ࡘࢠ-ࢲऄ-हऽॐक़-ॡॱ-ঀঅ-ঌএঐও-নপ-রলশ-হঽৎড়ঢ়য়-ৡৰৱਅ-ਊਏਐਓ-ਨਪ-ਰਲਲ਼ਵਸ਼ਸਹਖ਼-ੜਫ਼ੲ-ੴઅ-ઍએ-ઑઓ-નપ-રલળવ-હઽૐૠૡଅ-ଌଏଐଓ-ନପ-ରଲଳଵ-ହଽଡ଼ଢ଼ୟ-ୡୱஃஅ-ஊஎ-ஐஒ-கஙசஜஞடணதந-பம-ஹௐఅ-ఌఎ-ఐఒ-నప-హఽౘౙౠౡಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽೞೠೡೱೲഅ-ഌഎ-ഐഒ-ഺഽൎൠൡൺ-ൿඅ-ඖක-නඳ-රලව-ෆก-ะาำเ-ๆກຂຄງຈຊຍດ-ທນ-ຟມ-ຣລວສຫອ-ະາຳຽເ-ໄໆໜ-ໟༀཀ-ཇཉ-ཬྈ-ྌက-ဪဿၐ-ၕၚ-ၝၡၥၦၮ-ၰၵ-ႁႎႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚᎀ-ᎏᎠ-Ᏼᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛮ-ᛸᜀ-ᜌᜎ-ᜑᜠ-ᜱᝀ-ᝑᝠ-ᝬᝮ-ᝰក-ឳៗៜᠠ-ᡷᢀ-ᢨᢪᢰ-ᣵᤀ-ᤞᥐ-ᥭᥰ-ᥴᦀ-ᦫᧁ-ᧇᨀ-ᨖᨠ-ᩔᪧᬅ-ᬳᭅ-ᭋᮃ-ᮠᮮᮯᮺ-ᯥᰀ-ᰣᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳱᳵᳶᴀ-ᶿḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕ℘-ℝℤΩℨK-ℹℼ-ℿⅅ-ⅉⅎⅠ-ↈⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞ々-〇〡-〩〱-〵〸-〼ぁ-ゖ゛-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿌ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪꘫꙀ-ꙮꙿ-ꚝꚠ-ꛯꜗ-ꜟꜢ-ꞈꞋ-ꞎꞐ-ꞭꞰꞱꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠢꡀ-ꡳꢂ-ꢳꣲ-ꣷꣻꤊ-ꤥꤰ-ꥆꥠ-ꥼꦄ-ꦲꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨨꩀ-ꩂꩄ-ꩋꩠ-ꩶꩺꩾ-ꪯꪱꪵꪶꪹ-ꪽꫀꫂꫛ-ꫝꫠ-ꫪꫲ-ꫴꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭟꭤꭥꯀ-ꯢ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִײַ-ﬨשׁ-זּטּ-לּמּנּסּףּפּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ"; -var nonASCIIidentifierChars = "‌‍·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-٩ٰۖ-ۜ۟-۪ۤۧۨ-ۭ۰-۹ܑܰ-݊ަ-ް߀-߉߫-߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛ࣤ-ःऺ-़ा-ॏ॑-ॗॢॣ०-९ঁ-ঃ়া-ৄেৈো-্ৗৢৣ০-৯ਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑ੦-ੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣ૦-૯ଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣ୦-୯ஂா-ூெ-ைொ-்ௗ௦-௯ఀ-ఃా-ౄె-ైొ-్ౕౖౢౣ౦-౯ಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣ೦-೯ഁ-ഃാ-ൄെ-ൈൊ-്ൗൢൣ൦-൯ංඃ්ා-ුූෘ-ෟ෦-෯ෲෳัิ-ฺ็-๎๐-๙ັິ-ູົຼ່-ໍ໐-໙༘༙༠-༩༹༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှ၀-၉ၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏ-ႝ፝-፟፩-፱ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝០-៩᠋-᠍᠐-᠙ᢩᤠ-ᤫᤰ-᤻᥆-᥏ᦰ-ᧀᧈᧉ᧐-᧚ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼-᪉᪐-᪙᪰-᪽ᬀ-ᬄ᬴-᭄᭐-᭙᭫-᭳ᮀ-ᮂᮡ-ᮭ᮰-᮹᯦-᯳ᰤ-᰷᱀-᱉᱐-᱙᳐-᳔᳒-᳨᳭ᳲ-᳴᳸᳹᷀-᷵᷼-᷿‿⁀⁔⃐-⃥⃜⃡-⃰⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꘠-꘩꙯ꙴ-꙽ꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-꣄꣐-꣙꣠-꣱꤀-꤉ꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀꧐-꧙ꧥ꧰-꧹ꨩ-ꨶꩃꩌꩍ꩐-꩙ꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭꯰-꯹ﬞ︀-️︠-︭︳︴﹍-﹏0-9_"; - -var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); -var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); - -nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; - -// These are a run-length and offset encoded representation of the -// >0xffff code points that are a valid part of identifiers. The -// offset starts at 0x10000, and each pair of numbers represents an -// offset to the next range, and then a size of the range. They were -// generated by tools/generate-identifier-regex.js -var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 17, 26, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 99, 39, 9, 51, 157, 310, 10, 21, 11, 7, 153, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 98, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 26, 45, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 955, 52, 76, 44, 33, 24, 27, 35, 42, 34, 4, 0, 13, 47, 15, 3, 22, 0, 38, 17, 2, 24, 133, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 32, 4, 287, 47, 21, 1, 2, 0, 185, 46, 82, 47, 21, 0, 60, 42, 502, 63, 32, 0, 449, 56, 1288, 920, 104, 110, 2962, 1070, 13266, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 881, 68, 12, 0, 67, 12, 16481, 1, 3071, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 4149, 196, 1340, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42710, 42, 4148, 12, 221, 16355, 541]; -var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 1306, 2, 54, 14, 32, 9, 16, 3, 46, 10, 54, 9, 7, 2, 37, 13, 2, 9, 52, 0, 13, 2, 49, 13, 16, 9, 83, 11, 168, 11, 6, 9, 8, 2, 57, 0, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 316, 19, 13, 9, 214, 6, 3, 8, 112, 16, 16, 9, 82, 12, 9, 9, 535, 9, 20855, 9, 135, 4, 60, 6, 26, 9, 1016, 45, 17, 3, 19723, 1, 5319, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 4305, 6, 792618, 239]; - -// This has a complexity linear to the value of the code. The -// assumption is that looking up astral identifier characters is -// rare. -function isInAstralSet(code, set) { - var pos = 0x10000; - for (var i = 0; i < set.length; i += 2) { - pos += set[i]; - if (pos > code) return false; - pos += set[i + 1]; - if (pos >= code) return true; - } -} - -// Test whether a given character code starts an identifier. - -function isIdentifierStart(code, astral) { - if (code < 65) return code === 36; - if (code < 91) return true; - if (code < 97) return code === 95; - if (code < 123) return true; - if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)); - if (astral === false) return false; - return isInAstralSet(code, astralIdentifierStartCodes); -} - -// Test whether a given character is part of an identifier. - -function isIdentifierChar(code, astral) { - if (code < 48) return code === 36; - if (code < 58) return true; - if (code < 65) return false; - if (code < 91) return true; - if (code < 97) return code === 95; - if (code < 123) return true; - if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)); - if (astral === false) return false; - return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes); -} - -},{}],3:[function(_dereq_,module,exports){ -// Acorn is a tiny, fast JavaScript parser written in JavaScript. -// -// Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and -// various contributors and released under an MIT license. -// -// Git repositories for Acorn are available at -// -// http://marijnhaverbeke.nl/git/acorn -// https://github.com/ternjs/acorn.git -// -// Please use the [github bug tracker][ghbt] to report issues. -// -// [ghbt]: https://github.com/ternjs/acorn/issues -// -// This file defines the main parser interface. The library also comes -// with a [error-tolerant parser][dammit] and an -// [abstract syntax tree walker][walk], defined in other files. -// -// [dammit]: acorn_loose.js -// [walk]: util/walk.js - -"use strict"; - -exports.__esModule = true; -exports.parse = parse; -exports.parseExpressionAt = parseExpressionAt; -exports.tokenizer = tokenizer; - -var _state = _dereq_("./state"); - -_dereq_("./parseutil"); - -_dereq_("./statement"); - -_dereq_("./lval"); - -_dereq_("./expression"); - -_dereq_("./location"); - -exports.Parser = _state.Parser; -exports.plugins = _state.plugins; - -var _options = _dereq_("./options"); - -exports.defaultOptions = _options.defaultOptions; - -var _locutil = _dereq_("./locutil"); - -exports.Position = _locutil.Position; -exports.SourceLocation = _locutil.SourceLocation; -exports.getLineInfo = _locutil.getLineInfo; - -var _node = _dereq_("./node"); - -exports.Node = _node.Node; - -var _tokentype = _dereq_("./tokentype"); - -exports.TokenType = _tokentype.TokenType; -exports.tokTypes = _tokentype.types; - -var _tokencontext = _dereq_("./tokencontext"); - -exports.TokContext = _tokencontext.TokContext; -exports.tokContexts = _tokencontext.types; - -var _identifier = _dereq_("./identifier"); - -exports.isIdentifierChar = _identifier.isIdentifierChar; -exports.isIdentifierStart = _identifier.isIdentifierStart; - -var _tokenize = _dereq_("./tokenize"); - -exports.Token = _tokenize.Token; - -var _whitespace = _dereq_("./whitespace"); - -exports.isNewLine = _whitespace.isNewLine; -exports.lineBreak = _whitespace.lineBreak; -exports.lineBreakG = _whitespace.lineBreakG; -var version = "2.7.0"; - -exports.version = version; -// The main exported interface (under `self.acorn` when in the -// browser) is a `parse` function that takes a code string and -// returns an abstract syntax tree as specified by [Mozilla parser -// API][api]. -// -// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API - -function parse(input, options) { - return new _state.Parser(options, input).parse(); -} - -// This function tries to parse a single expression at a given -// offset in a string. Useful for parsing mixed-language formats -// that embed JavaScript expressions. - -function parseExpressionAt(input, pos, options) { - var p = new _state.Parser(options, input, pos); - p.nextToken(); - return p.parseExpression(); -} - -// Acorn is organized as a tokenizer and a recursive-descent parser. -// The `tokenizer` export provides an interface to the tokenizer. - -function tokenizer(input, options) { - return new _state.Parser(options, input); -} - -},{"./expression":1,"./identifier":2,"./location":4,"./locutil":5,"./lval":6,"./node":7,"./options":8,"./parseutil":9,"./state":10,"./statement":11,"./tokencontext":12,"./tokenize":13,"./tokentype":14,"./whitespace":16}],4:[function(_dereq_,module,exports){ -"use strict"; - -var _state = _dereq_("./state"); - -var _locutil = _dereq_("./locutil"); - -var pp = _state.Parser.prototype; - -// This function is used to raise exceptions on parse errors. It -// takes an offset integer (into the current `input`) to indicate -// the location of the error, attaches the position to the end -// of the error message, and then raises a `SyntaxError` with that -// message. - -pp.raise = function (pos, message) { - var loc = _locutil.getLineInfo(this.input, pos); - message += " (" + loc.line + ":" + loc.column + ")"; - var err = new SyntaxError(message); - err.pos = pos;err.loc = loc;err.raisedAt = this.pos; - throw err; -}; - -pp.curPosition = function () { - if (this.options.locations) { - return new _locutil.Position(this.curLine, this.pos - this.lineStart); - } -}; - -},{"./locutil":5,"./state":10}],5:[function(_dereq_,module,exports){ -"use strict"; - -exports.__esModule = true; -exports.getLineInfo = getLineInfo; - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var _whitespace = _dereq_("./whitespace"); - -// These are used when `options.locations` is on, for the -// `startLoc` and `endLoc` properties. - -var Position = (function () { - function Position(line, col) { - _classCallCheck(this, Position); - - this.line = line; - this.column = col; - } - - Position.prototype.offset = function offset(n) { - return new Position(this.line, this.column + n); - }; - - return Position; -})(); - -exports.Position = Position; - -var SourceLocation = function SourceLocation(p, start, end) { - _classCallCheck(this, SourceLocation); - - this.start = start; - this.end = end; - if (p.sourceFile !== null) this.source = p.sourceFile; -} - -// The `getLineInfo` function is mostly useful when the -// `locations` option is off (for performance reasons) and you -// want to find the line/column position for a given character -// offset. `input` should be the code string that the offset refers -// into. - -; - -exports.SourceLocation = SourceLocation; - -function getLineInfo(input, offset) { - for (var line = 1, cur = 0;;) { - _whitespace.lineBreakG.lastIndex = cur; - var match = _whitespace.lineBreakG.exec(input); - if (match && match.index < offset) { - ++line; - cur = match.index + match[0].length; - } else { - return new Position(line, offset - cur); - } - } -} - -},{"./whitespace":16}],6:[function(_dereq_,module,exports){ -"use strict"; - -var _tokentype = _dereq_("./tokentype"); - -var _state = _dereq_("./state"); - -var _util = _dereq_("./util"); - -var pp = _state.Parser.prototype; - -// Convert existing expression atom to assignable pattern -// if possible. - -pp.toAssignable = function (node, isBinding) { - if (this.options.ecmaVersion >= 6 && node) { - switch (node.type) { - case "Identifier": - case "ObjectPattern": - case "ArrayPattern": - break; - - case "ObjectExpression": - node.type = "ObjectPattern"; - for (var i = 0; i < node.properties.length; i++) { - var prop = node.properties[i]; - if (prop.kind !== "init") this.raise(prop.key.start, "Object pattern can't contain getter or setter"); - this.toAssignable(prop.value, isBinding); - } - break; - - case "ArrayExpression": - node.type = "ArrayPattern"; - this.toAssignableList(node.elements, isBinding); - break; - - case "AssignmentExpression": - if (node.operator === "=") { - node.type = "AssignmentPattern"; - delete node.operator; - // falls through to AssignmentPattern - } else { - this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); - break; - } - - case "AssignmentPattern": - if (node.right.type === "YieldExpression") this.raise(node.right.start, "Yield expression cannot be a default value"); - break; - - case "ParenthesizedExpression": - node.expression = this.toAssignable(node.expression, isBinding); - break; - - case "MemberExpression": - if (!isBinding) break; - - default: - this.raise(node.start, "Assigning to rvalue"); - } - } - return node; -}; - -// Convert list of expression atoms to binding list. - -pp.toAssignableList = function (exprList, isBinding) { - var end = exprList.length; - if (end) { - var last = exprList[end - 1]; - if (last && last.type == "RestElement") { - --end; - } else if (last && last.type == "SpreadElement") { - last.type = "RestElement"; - var arg = last.argument; - this.toAssignable(arg, isBinding); - if (arg.type !== "Identifier" && arg.type !== "MemberExpression" && arg.type !== "ArrayPattern") this.unexpected(arg.start); - --end; - } - - if (isBinding && last.type === "RestElement" && last.argument.type !== "Identifier") this.unexpected(last.argument.start); - } - for (var i = 0; i < end; i++) { - var elt = exprList[i]; - if (elt) this.toAssignable(elt, isBinding); - } - return exprList; -}; - -// Parses spread element. - -pp.parseSpread = function (refDestructuringErrors) { - var node = this.startNode(); - this.next(); - node.argument = this.parseMaybeAssign(refDestructuringErrors); - return this.finishNode(node, "SpreadElement"); -}; - -pp.parseRest = function (allowNonIdent) { - var node = this.startNode(); - this.next(); - - // RestElement inside of a function parameter must be an identifier - if (allowNonIdent) node.argument = this.type === _tokentype.types.name ? this.parseIdent() : this.unexpected();else node.argument = this.type === _tokentype.types.name || this.type === _tokentype.types.bracketL ? this.parseBindingAtom() : this.unexpected(); - - return this.finishNode(node, "RestElement"); -}; - -// Parses lvalue (assignable) atom. - -pp.parseBindingAtom = function () { - if (this.options.ecmaVersion < 6) return this.parseIdent(); - switch (this.type) { - case _tokentype.types.name: - return this.parseIdent(); - - case _tokentype.types.bracketL: - var node = this.startNode(); - this.next(); - node.elements = this.parseBindingList(_tokentype.types.bracketR, true, true); - return this.finishNode(node, "ArrayPattern"); - - case _tokentype.types.braceL: - return this.parseObj(true); - - default: - this.unexpected(); - } -}; - -pp.parseBindingList = function (close, allowEmpty, allowTrailingComma, allowNonIdent) { - var elts = [], - first = true; - while (!this.eat(close)) { - if (first) first = false;else this.expect(_tokentype.types.comma); - if (allowEmpty && this.type === _tokentype.types.comma) { - elts.push(null); - } else if (allowTrailingComma && this.afterTrailingComma(close)) { - break; - } else if (this.type === _tokentype.types.ellipsis) { - var rest = this.parseRest(allowNonIdent); - this.parseBindingListItem(rest); - elts.push(rest); - this.expect(close); - break; - } else { - var elem = this.parseMaybeDefault(this.start, this.startLoc); - this.parseBindingListItem(elem); - elts.push(elem); - } - } - return elts; -}; - -pp.parseBindingListItem = function (param) { - return param; -}; - -// Parses assignment pattern around given atom if possible. - -pp.parseMaybeDefault = function (startPos, startLoc, left) { - left = left || this.parseBindingAtom(); - if (this.options.ecmaVersion < 6 || !this.eat(_tokentype.types.eq)) return left; - var node = this.startNodeAt(startPos, startLoc); - node.left = left; - node.right = this.parseMaybeAssign(); - return this.finishNode(node, "AssignmentPattern"); -}; - -// Verify that a node is an lval — something that can be assigned -// to. - -pp.checkLVal = function (expr, isBinding, checkClashes) { - switch (expr.type) { - case "Identifier": - if (this.strict && this.reservedWordsStrictBind.test(expr.name)) this.raise(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); - if (checkClashes) { - if (_util.has(checkClashes, expr.name)) this.raise(expr.start, "Argument name clash"); - checkClashes[expr.name] = true; - } - break; - - case "MemberExpression": - if (isBinding) this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression"); - break; - - case "ObjectPattern": - for (var i = 0; i < expr.properties.length; i++) { - this.checkLVal(expr.properties[i].value, isBinding, checkClashes); - }break; - - case "ArrayPattern": - for (var i = 0; i < expr.elements.length; i++) { - var elem = expr.elements[i]; - if (elem) this.checkLVal(elem, isBinding, checkClashes); - } - break; - - case "AssignmentPattern": - this.checkLVal(expr.left, isBinding, checkClashes); - break; - - case "RestElement": - this.checkLVal(expr.argument, isBinding, checkClashes); - break; - - case "ParenthesizedExpression": - this.checkLVal(expr.expression, isBinding, checkClashes); - break; - - default: - this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " rvalue"); - } -}; - -},{"./state":10,"./tokentype":14,"./util":15}],7:[function(_dereq_,module,exports){ -"use strict"; - -exports.__esModule = true; - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var _state = _dereq_("./state"); - -var _locutil = _dereq_("./locutil"); - -var Node = function Node(parser, pos, loc) { - _classCallCheck(this, Node); - - this.type = ""; - this.start = pos; - this.end = 0; - if (parser.options.locations) this.loc = new _locutil.SourceLocation(parser, loc); - if (parser.options.directSourceFile) this.sourceFile = parser.options.directSourceFile; - if (parser.options.ranges) this.range = [pos, 0]; -} - -// Start an AST node, attaching a start offset. - -; - -exports.Node = Node; -var pp = _state.Parser.prototype; - -pp.startNode = function () { - return new Node(this, this.start, this.startLoc); -}; - -pp.startNodeAt = function (pos, loc) { - return new Node(this, pos, loc); -}; - -// Finish an AST node, adding `type` and `end` properties. - -function finishNodeAt(node, type, pos, loc) { - node.type = type; - node.end = pos; - if (this.options.locations) node.loc.end = loc; - if (this.options.ranges) node.range[1] = pos; - return node; -} - -pp.finishNode = function (node, type) { - return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc); -}; - -// Finish node at given position - -pp.finishNodeAt = function (node, type, pos, loc) { - return finishNodeAt.call(this, node, type, pos, loc); -}; - -},{"./locutil":5,"./state":10}],8:[function(_dereq_,module,exports){ -"use strict"; - -exports.__esModule = true; -exports.getOptions = getOptions; - -var _util = _dereq_("./util"); - -var _locutil = _dereq_("./locutil"); - -// A second optional argument can be given to further configure -// the parser process. These options are recognized: - -var defaultOptions = { - // `ecmaVersion` indicates the ECMAScript version to parse. Must - // be either 3, or 5, or 6. This influences support for strict - // mode, the set of reserved words, support for getters and - // setters and other features. - ecmaVersion: 5, - // Source type ("script" or "module") for different semantics - sourceType: "script", - // `onInsertedSemicolon` can be a callback that will be called - // when a semicolon is automatically inserted. It will be passed - // th position of the comma as an offset, and if `locations` is - // enabled, it is given the location as a `{line, column}` object - // as second argument. - onInsertedSemicolon: null, - // `onTrailingComma` is similar to `onInsertedSemicolon`, but for - // trailing commas. - onTrailingComma: null, - // By default, reserved words are only enforced if ecmaVersion >= 5. - // Set `allowReserved` to a boolean value to explicitly turn this on - // an off. When this option has the value "never", reserved words - // and keywords can also not be used as property names. - allowReserved: null, - // When enabled, a return at the top level is not considered an - // error. - allowReturnOutsideFunction: false, - // When enabled, import/export statements are not constrained to - // appearing at the top of the program. - allowImportExportEverywhere: false, - // When enabled, hashbang directive in the beginning of file - // is allowed and treated as a line comment. - allowHashBang: false, - // When `locations` is on, `loc` properties holding objects with - // `start` and `end` properties in `{line, column}` form (with - // line being 1-based and column 0-based) will be attached to the - // nodes. - locations: false, - // A function can be passed as `onToken` option, which will - // cause Acorn to call that function with object in the same - // format as tokens returned from `tokenizer().getToken()`. Note - // that you are not allowed to call the parser from the - // callback—that will corrupt its internal state. - onToken: null, - // A function can be passed as `onComment` option, which will - // cause Acorn to call that function with `(block, text, start, - // end)` parameters whenever a comment is skipped. `block` is a - // boolean indicating whether this is a block (`/* */`) comment, - // `text` is the content of the comment, and `start` and `end` are - // character offsets that denote the start and end of the comment. - // When the `locations` option is on, two more parameters are - // passed, the full `{line, column}` locations of the start and - // end of the comments. Note that you are not allowed to call the - // parser from the callback—that will corrupt its internal state. - onComment: null, - // Nodes have their start and end characters offsets recorded in - // `start` and `end` properties (directly on the node, rather than - // the `loc` object, which holds line/column data. To also add a - // [semi-standardized][range] `range` property holding a `[start, - // end]` array with the same numbers, set the `ranges` option to - // `true`. - // - // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 - ranges: false, - // It is possible to parse multiple files into a single AST by - // passing the tree produced by parsing the first file as - // `program` option in subsequent parses. This will add the - // toplevel forms of the parsed file to the `Program` (top) node - // of an existing parse tree. - program: null, - // When `locations` is on, you can pass this to record the source - // file in every node's `loc` object. - sourceFile: null, - // This value, if given, is stored in every node, whether - // `locations` is on or off. - directSourceFile: null, - // When enabled, parenthesized expressions are represented by - // (non-standard) ParenthesizedExpression nodes - preserveParens: false, - plugins: {} -}; - -exports.defaultOptions = defaultOptions; -// Interpret and default an options object - -function getOptions(opts) { - var options = {}; - for (var opt in defaultOptions) { - options[opt] = opts && _util.has(opts, opt) ? opts[opt] : defaultOptions[opt]; - }if (options.allowReserved == null) options.allowReserved = options.ecmaVersion < 5; - - if (_util.isArray(options.onToken)) { - (function () { - var tokens = options.onToken; - options.onToken = function (token) { - return tokens.push(token); - }; - })(); - } - if (_util.isArray(options.onComment)) options.onComment = pushComment(options, options.onComment); - - return options; -} - -function pushComment(options, array) { - return function (block, text, start, end, startLoc, endLoc) { - var comment = { - type: block ? 'Block' : 'Line', - value: text, - start: start, - end: end - }; - if (options.locations) comment.loc = new _locutil.SourceLocation(this, startLoc, endLoc); - if (options.ranges) comment.range = [start, end]; - array.push(comment); - }; -} - -},{"./locutil":5,"./util":15}],9:[function(_dereq_,module,exports){ -"use strict"; - -var _tokentype = _dereq_("./tokentype"); - -var _state = _dereq_("./state"); - -var _whitespace = _dereq_("./whitespace"); - -var pp = _state.Parser.prototype; - -// ## Parser utilities - -// Test whether a statement node is the string literal `"use strict"`. - -pp.isUseStrict = function (stmt) { - return this.options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" && stmt.expression.type === "Literal" && stmt.expression.raw.slice(1, -1) === "use strict"; -}; - -// Predicate that tests whether the next token is of the given -// type, and if yes, consumes it as a side effect. - -pp.eat = function (type) { - if (this.type === type) { - this.next(); - return true; - } else { - return false; - } -}; - -// Tests whether parsed token is a contextual keyword. - -pp.isContextual = function (name) { - return this.type === _tokentype.types.name && this.value === name; -}; - -// Consumes contextual keyword if possible. - -pp.eatContextual = function (name) { - return this.value === name && this.eat(_tokentype.types.name); -}; - -// Asserts that following token is given contextual keyword. - -pp.expectContextual = function (name) { - if (!this.eatContextual(name)) this.unexpected(); -}; - -// Test whether a semicolon can be inserted at the current position. - -pp.canInsertSemicolon = function () { - return this.type === _tokentype.types.eof || this.type === _tokentype.types.braceR || _whitespace.lineBreak.test(this.input.slice(this.lastTokEnd, this.start)); -}; - -pp.insertSemicolon = function () { - if (this.canInsertSemicolon()) { - if (this.options.onInsertedSemicolon) this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); - return true; - } -}; - -// Consume a semicolon, or, failing that, see if we are allowed to -// pretend that there is a semicolon at this position. - -pp.semicolon = function () { - if (!this.eat(_tokentype.types.semi) && !this.insertSemicolon()) this.unexpected(); -}; - -pp.afterTrailingComma = function (tokType) { - if (this.type == tokType) { - if (this.options.onTrailingComma) this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); - this.next(); - return true; - } -}; - -// Expect a token of a given type. If found, consume it, otherwise, -// raise an unexpected token error. - -pp.expect = function (type) { - this.eat(type) || this.unexpected(); -}; - -// Raise an unexpected token error. - -pp.unexpected = function (pos) { - this.raise(pos != null ? pos : this.start, "Unexpected token"); -}; - -pp.checkPatternErrors = function (refDestructuringErrors, andThrow) { - var pos = refDestructuringErrors && refDestructuringErrors.trailingComma; - if (!andThrow) return !!pos; - if (pos) this.raise(pos, "Trailing comma is not permitted in destructuring patterns"); -}; - -pp.checkExpressionErrors = function (refDestructuringErrors, andThrow) { - var pos = refDestructuringErrors && refDestructuringErrors.shorthandAssign; - if (!andThrow) return !!pos; - if (pos) this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns"); -}; - -},{"./state":10,"./tokentype":14,"./whitespace":16}],10:[function(_dereq_,module,exports){ -"use strict"; - -exports.__esModule = true; - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var _identifier = _dereq_("./identifier"); - -var _tokentype = _dereq_("./tokentype"); - -var _whitespace = _dereq_("./whitespace"); - -var _options = _dereq_("./options"); - -// Registered plugins -var plugins = {}; - -exports.plugins = plugins; -function keywordRegexp(words) { - return new RegExp("^(" + words.replace(/ /g, "|") + ")$"); -} - -var Parser = (function () { - function Parser(options, input, startPos) { - _classCallCheck(this, Parser); - - this.options = options = _options.getOptions(options); - this.sourceFile = options.sourceFile; - this.keywords = keywordRegexp(_identifier.keywords[options.ecmaVersion >= 6 ? 6 : 5]); - var reserved = options.allowReserved ? "" : _identifier.reservedWords[options.ecmaVersion] + (options.sourceType == "module" ? " await" : ""); - this.reservedWords = keywordRegexp(reserved); - var reservedStrict = (reserved ? reserved + " " : "") + _identifier.reservedWords.strict; - this.reservedWordsStrict = keywordRegexp(reservedStrict); - this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + _identifier.reservedWords.strictBind); - this.input = String(input); - - // Used to signal to callers of `readWord1` whether the word - // contained any escape sequences. This is needed because words with - // escape sequences must not be interpreted as keywords. - this.containsEsc = false; - - // Load plugins - this.loadPlugins(options.plugins); - - // Set up token state - - // The current position of the tokenizer in the input. - if (startPos) { - this.pos = startPos; - this.lineStart = Math.max(0, this.input.lastIndexOf("\n", startPos)); - this.curLine = this.input.slice(0, this.lineStart).split(_whitespace.lineBreak).length; - } else { - this.pos = this.lineStart = 0; - this.curLine = 1; - } - - // Properties of the current token: - // Its type - this.type = _tokentype.types.eof; - // For tokens that include more information than their type, the value - this.value = null; - // Its start and end offset - this.start = this.end = this.pos; - // And, if locations are used, the {line, column} object - // corresponding to those offsets - this.startLoc = this.endLoc = this.curPosition(); - - // Position information for the previous token - this.lastTokEndLoc = this.lastTokStartLoc = null; - this.lastTokStart = this.lastTokEnd = this.pos; - - // The context stack is used to superficially track syntactic - // context to predict whether a regular expression is allowed in a - // given position. - this.context = this.initialContext(); - this.exprAllowed = true; - - // Figure out if it's a module code. - this.strict = this.inModule = options.sourceType === "module"; - - // Used to signify the start of a potential arrow function - this.potentialArrowAt = -1; - - // Flags to track whether we are in a function, a generator. - this.inFunction = this.inGenerator = false; - // Labels in scope. - this.labels = []; - - // If enabled, skip leading hashbang line. - if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === '#!') this.skipLineComment(2); - } - - // DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them - - Parser.prototype.isKeyword = function isKeyword(word) { - return this.keywords.test(word); - }; - - Parser.prototype.isReservedWord = function isReservedWord(word) { - return this.reservedWords.test(word); - }; - - Parser.prototype.extend = function extend(name, f) { - this[name] = f(this[name]); - }; - - Parser.prototype.loadPlugins = function loadPlugins(pluginConfigs) { - for (var _name in pluginConfigs) { - var plugin = plugins[_name]; - if (!plugin) throw new Error("Plugin '" + _name + "' not found"); - plugin(this, pluginConfigs[_name]); - } - }; - - Parser.prototype.parse = function parse() { - var node = this.options.program || this.startNode(); - this.nextToken(); - return this.parseTopLevel(node); - }; - - return Parser; -})(); - -exports.Parser = Parser; - -},{"./identifier":2,"./options":8,"./tokentype":14,"./whitespace":16}],11:[function(_dereq_,module,exports){ -"use strict"; - -var _tokentype = _dereq_("./tokentype"); - -var _state = _dereq_("./state"); - -var _whitespace = _dereq_("./whitespace"); - -var pp = _state.Parser.prototype; - -// ### Statement parsing - -// Parse a program. Initializes the parser, reads any number of -// statements, and wraps them in a Program node. Optionally takes a -// `program` argument. If present, the statements will be appended -// to its body instead of creating a new node. - -pp.parseTopLevel = function (node) { - var first = true; - if (!node.body) node.body = []; - while (this.type !== _tokentype.types.eof) { - var stmt = this.parseStatement(true, true); - node.body.push(stmt); - if (first) { - if (this.isUseStrict(stmt)) this.setStrict(true); - first = false; - } - } - this.next(); - if (this.options.ecmaVersion >= 6) { - node.sourceType = this.options.sourceType; - } - return this.finishNode(node, "Program"); -}; - -var loopLabel = { kind: "loop" }, - switchLabel = { kind: "switch" }; - -// Parse a single statement. -// -// If expecting a statement and finding a slash operator, parse a -// regular expression literal. This is to handle cases like -// `if (foo) /blah/.exec(foo)`, where looking at the previous token -// does not help. - -pp.parseStatement = function (declaration, topLevel) { - var starttype = this.type, - node = this.startNode(); - - // Most types of statements are recognized by the keyword they - // start with. Many are trivial to parse, some require a bit of - // complexity. - - switch (starttype) { - case _tokentype.types._break:case _tokentype.types._continue: - return this.parseBreakContinueStatement(node, starttype.keyword); - case _tokentype.types._debugger: - return this.parseDebuggerStatement(node); - case _tokentype.types._do: - return this.parseDoStatement(node); - case _tokentype.types._for: - return this.parseForStatement(node); - case _tokentype.types._function: - if (!declaration && this.options.ecmaVersion >= 6) this.unexpected(); - return this.parseFunctionStatement(node); - case _tokentype.types._class: - if (!declaration) this.unexpected(); - return this.parseClass(node, true); - case _tokentype.types._if: - return this.parseIfStatement(node); - case _tokentype.types._return: - return this.parseReturnStatement(node); - case _tokentype.types._switch: - return this.parseSwitchStatement(node); - case _tokentype.types._throw: - return this.parseThrowStatement(node); - case _tokentype.types._try: - return this.parseTryStatement(node); - case _tokentype.types._let:case _tokentype.types._const: - if (!declaration) this.unexpected(); // NOTE: falls through to _var - case _tokentype.types._var: - return this.parseVarStatement(node, starttype); - case _tokentype.types._while: - return this.parseWhileStatement(node); - case _tokentype.types._with: - return this.parseWithStatement(node); - case _tokentype.types.braceL: - return this.parseBlock(); - case _tokentype.types.semi: - return this.parseEmptyStatement(node); - case _tokentype.types._export: - case _tokentype.types._import: - if (!this.options.allowImportExportEverywhere) { - if (!topLevel) this.raise(this.start, "'import' and 'export' may only appear at the top level"); - if (!this.inModule) this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); - } - return starttype === _tokentype.types._import ? this.parseImport(node) : this.parseExport(node); - - // If the statement does not start with a statement keyword or a - // brace, it's an ExpressionStatement or LabeledStatement. We - // simply start parsing an expression, and afterwards, if the - // next token is a colon and the expression was a simple - // Identifier node, we switch to interpreting it as a label. - default: - var maybeName = this.value, - expr = this.parseExpression(); - if (starttype === _tokentype.types.name && expr.type === "Identifier" && this.eat(_tokentype.types.colon)) return this.parseLabeledStatement(node, maybeName, expr);else return this.parseExpressionStatement(node, expr); - } -}; - -pp.parseBreakContinueStatement = function (node, keyword) { - var isBreak = keyword == "break"; - this.next(); - if (this.eat(_tokentype.types.semi) || this.insertSemicolon()) node.label = null;else if (this.type !== _tokentype.types.name) this.unexpected();else { - node.label = this.parseIdent(); - this.semicolon(); - } - - // Verify that there is an actual destination to break or - // continue to. - for (var i = 0; i < this.labels.length; ++i) { - var lab = this.labels[i]; - if (node.label == null || lab.name === node.label.name) { - if (lab.kind != null && (isBreak || lab.kind === "loop")) break; - if (node.label && isBreak) break; - } - } - if (i === this.labels.length) this.raise(node.start, "Unsyntactic " + keyword); - return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement"); -}; - -pp.parseDebuggerStatement = function (node) { - this.next(); - this.semicolon(); - return this.finishNode(node, "DebuggerStatement"); -}; - -pp.parseDoStatement = function (node) { - this.next(); - this.labels.push(loopLabel); - node.body = this.parseStatement(false); - this.labels.pop(); - this.expect(_tokentype.types._while); - node.test = this.parseParenExpression(); - if (this.options.ecmaVersion >= 6) this.eat(_tokentype.types.semi);else this.semicolon(); - return this.finishNode(node, "DoWhileStatement"); -}; - -// Disambiguating between a `for` and a `for`/`in` or `for`/`of` -// loop is non-trivial. Basically, we have to parse the init `var` -// statement or expression, disallowing the `in` operator (see -// the second parameter to `parseExpression`), and then check -// whether the next token is `in` or `of`. When there is no init -// part (semicolon immediately after the opening parenthesis), it -// is a regular `for` loop. - -pp.parseForStatement = function (node) { - this.next(); - this.labels.push(loopLabel); - this.expect(_tokentype.types.parenL); - if (this.type === _tokentype.types.semi) return this.parseFor(node, null); - if (this.type === _tokentype.types._var || this.type === _tokentype.types._let || this.type === _tokentype.types._const) { - var _init = this.startNode(), - varKind = this.type; - this.next(); - this.parseVar(_init, true, varKind); - this.finishNode(_init, "VariableDeclaration"); - if ((this.type === _tokentype.types._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) && _init.declarations.length === 1 && !(varKind !== _tokentype.types._var && _init.declarations[0].init)) return this.parseForIn(node, _init); - return this.parseFor(node, _init); - } - var refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 }; - var init = this.parseExpression(true, refDestructuringErrors); - if (this.type === _tokentype.types._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) { - this.checkPatternErrors(refDestructuringErrors, true); - this.toAssignable(init); - this.checkLVal(init); - return this.parseForIn(node, init); - } else { - this.checkExpressionErrors(refDestructuringErrors, true); - } - return this.parseFor(node, init); -}; - -pp.parseFunctionStatement = function (node) { - this.next(); - return this.parseFunction(node, true); -}; - -pp.parseIfStatement = function (node) { - this.next(); - node.test = this.parseParenExpression(); - node.consequent = this.parseStatement(false); - node.alternate = this.eat(_tokentype.types._else) ? this.parseStatement(false) : null; - return this.finishNode(node, "IfStatement"); -}; - -pp.parseReturnStatement = function (node) { - if (!this.inFunction && !this.options.allowReturnOutsideFunction) this.raise(this.start, "'return' outside of function"); - this.next(); - - // In `return` (and `break`/`continue`), the keywords with - // optional arguments, we eagerly look for a semicolon or the - // possibility to insert one. - - if (this.eat(_tokentype.types.semi) || this.insertSemicolon()) node.argument = null;else { - node.argument = this.parseExpression();this.semicolon(); - } - return this.finishNode(node, "ReturnStatement"); -}; - -pp.parseSwitchStatement = function (node) { - this.next(); - node.discriminant = this.parseParenExpression(); - node.cases = []; - this.expect(_tokentype.types.braceL); - this.labels.push(switchLabel); - - // Statements under must be grouped (by label) in SwitchCase - // nodes. `cur` is used to keep the node that we are currently - // adding statements to. - - for (var cur, sawDefault = false; this.type != _tokentype.types.braceR;) { - if (this.type === _tokentype.types._case || this.type === _tokentype.types._default) { - var isCase = this.type === _tokentype.types._case; - if (cur) this.finishNode(cur, "SwitchCase"); - node.cases.push(cur = this.startNode()); - cur.consequent = []; - this.next(); - if (isCase) { - cur.test = this.parseExpression(); - } else { - if (sawDefault) this.raise(this.lastTokStart, "Multiple default clauses"); - sawDefault = true; - cur.test = null; - } - this.expect(_tokentype.types.colon); - } else { - if (!cur) this.unexpected(); - cur.consequent.push(this.parseStatement(true)); - } - } - if (cur) this.finishNode(cur, "SwitchCase"); - this.next(); // Closing brace - this.labels.pop(); - return this.finishNode(node, "SwitchStatement"); -}; - -pp.parseThrowStatement = function (node) { - this.next(); - if (_whitespace.lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) this.raise(this.lastTokEnd, "Illegal newline after throw"); - node.argument = this.parseExpression(); - this.semicolon(); - return this.finishNode(node, "ThrowStatement"); -}; - -// Reused empty array added for node fields that are always empty. - -var empty = []; - -pp.parseTryStatement = function (node) { - this.next(); - node.block = this.parseBlock(); - node.handler = null; - if (this.type === _tokentype.types._catch) { - var clause = this.startNode(); - this.next(); - this.expect(_tokentype.types.parenL); - clause.param = this.parseBindingAtom(); - this.checkLVal(clause.param, true); - this.expect(_tokentype.types.parenR); - clause.body = this.parseBlock(); - node.handler = this.finishNode(clause, "CatchClause"); - } - node.finalizer = this.eat(_tokentype.types._finally) ? this.parseBlock() : null; - if (!node.handler && !node.finalizer) this.raise(node.start, "Missing catch or finally clause"); - return this.finishNode(node, "TryStatement"); -}; - -pp.parseVarStatement = function (node, kind) { - this.next(); - this.parseVar(node, false, kind); - this.semicolon(); - return this.finishNode(node, "VariableDeclaration"); -}; - -pp.parseWhileStatement = function (node) { - this.next(); - node.test = this.parseParenExpression(); - this.labels.push(loopLabel); - node.body = this.parseStatement(false); - this.labels.pop(); - return this.finishNode(node, "WhileStatement"); -}; - -pp.parseWithStatement = function (node) { - if (this.strict) this.raise(this.start, "'with' in strict mode"); - this.next(); - node.object = this.parseParenExpression(); - node.body = this.parseStatement(false); - return this.finishNode(node, "WithStatement"); -}; - -pp.parseEmptyStatement = function (node) { - this.next(); - return this.finishNode(node, "EmptyStatement"); -}; - -pp.parseLabeledStatement = function (node, maybeName, expr) { - for (var i = 0; i < this.labels.length; ++i) { - if (this.labels[i].name === maybeName) this.raise(expr.start, "Label '" + maybeName + "' is already declared"); - }var kind = this.type.isLoop ? "loop" : this.type === _tokentype.types._switch ? "switch" : null; - for (var i = this.labels.length - 1; i >= 0; i--) { - var label = this.labels[i]; - if (label.statementStart == node.start) { - label.statementStart = this.start; - label.kind = kind; - } else break; - } - this.labels.push({ name: maybeName, kind: kind, statementStart: this.start }); - node.body = this.parseStatement(true); - this.labels.pop(); - node.label = expr; - return this.finishNode(node, "LabeledStatement"); -}; - -pp.parseExpressionStatement = function (node, expr) { - node.expression = expr; - this.semicolon(); - return this.finishNode(node, "ExpressionStatement"); -}; - -// Parse a semicolon-enclosed block of statements, handling `"use -// strict"` declarations when `allowStrict` is true (used for -// function bodies). - -pp.parseBlock = function (allowStrict) { - var node = this.startNode(), - first = true, - oldStrict = undefined; - node.body = []; - this.expect(_tokentype.types.braceL); - while (!this.eat(_tokentype.types.braceR)) { - var stmt = this.parseStatement(true); - node.body.push(stmt); - if (first && allowStrict && this.isUseStrict(stmt)) { - oldStrict = this.strict; - this.setStrict(this.strict = true); - } - first = false; - } - if (oldStrict === false) this.setStrict(false); - return this.finishNode(node, "BlockStatement"); -}; - -// Parse a regular `for` loop. The disambiguation code in -// `parseStatement` will already have parsed the init statement or -// expression. - -pp.parseFor = function (node, init) { - node.init = init; - this.expect(_tokentype.types.semi); - node.test = this.type === _tokentype.types.semi ? null : this.parseExpression(); - this.expect(_tokentype.types.semi); - node.update = this.type === _tokentype.types.parenR ? null : this.parseExpression(); - this.expect(_tokentype.types.parenR); - node.body = this.parseStatement(false); - this.labels.pop(); - return this.finishNode(node, "ForStatement"); -}; - -// Parse a `for`/`in` and `for`/`of` loop, which are almost -// same from parser's perspective. - -pp.parseForIn = function (node, init) { - var type = this.type === _tokentype.types._in ? "ForInStatement" : "ForOfStatement"; - this.next(); - node.left = init; - node.right = this.parseExpression(); - this.expect(_tokentype.types.parenR); - node.body = this.parseStatement(false); - this.labels.pop(); - return this.finishNode(node, type); -}; - -// Parse a list of variable declarations. - -pp.parseVar = function (node, isFor, kind) { - node.declarations = []; - node.kind = kind.keyword; - for (;;) { - var decl = this.startNode(); - this.parseVarId(decl); - if (this.eat(_tokentype.types.eq)) { - decl.init = this.parseMaybeAssign(isFor); - } else if (kind === _tokentype.types._const && !(this.type === _tokentype.types._in || this.options.ecmaVersion >= 6 && this.isContextual("of"))) { - this.unexpected(); - } else if (decl.id.type != "Identifier" && !(isFor && (this.type === _tokentype.types._in || this.isContextual("of")))) { - this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value"); - } else { - decl.init = null; - } - node.declarations.push(this.finishNode(decl, "VariableDeclarator")); - if (!this.eat(_tokentype.types.comma)) break; - } - return node; -}; - -pp.parseVarId = function (decl) { - decl.id = this.parseBindingAtom(); - this.checkLVal(decl.id, true); -}; - -// Parse a function declaration or literal (depending on the -// `isStatement` parameter). - -pp.parseFunction = function (node, isStatement, allowExpressionBody) { - this.initFunction(node); - if (this.options.ecmaVersion >= 6) node.generator = this.eat(_tokentype.types.star); - if (isStatement || this.type === _tokentype.types.name) node.id = this.parseIdent(); - this.parseFunctionParams(node); - this.parseFunctionBody(node, allowExpressionBody); - return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression"); -}; - -pp.parseFunctionParams = function (node) { - this.expect(_tokentype.types.parenL); - node.params = this.parseBindingList(_tokentype.types.parenR, false, false, true); -}; - -// Parse a class declaration or literal (depending on the -// `isStatement` parameter). - -pp.parseClass = function (node, isStatement) { - this.next(); - this.parseClassId(node, isStatement); - this.parseClassSuper(node); - var classBody = this.startNode(); - var hadConstructor = false; - classBody.body = []; - this.expect(_tokentype.types.braceL); - while (!this.eat(_tokentype.types.braceR)) { - if (this.eat(_tokentype.types.semi)) continue; - var method = this.startNode(); - var isGenerator = this.eat(_tokentype.types.star); - var isMaybeStatic = this.type === _tokentype.types.name && this.value === "static"; - this.parsePropertyName(method); - method["static"] = isMaybeStatic && this.type !== _tokentype.types.parenL; - if (method["static"]) { - if (isGenerator) this.unexpected(); - isGenerator = this.eat(_tokentype.types.star); - this.parsePropertyName(method); - } - method.kind = "method"; - var isGetSet = false; - if (!method.computed) { - var key = method.key; - - if (!isGenerator && key.type === "Identifier" && this.type !== _tokentype.types.parenL && (key.name === "get" || key.name === "set")) { - isGetSet = true; - method.kind = key.name; - key = this.parsePropertyName(method); - } - if (!method["static"] && (key.type === "Identifier" && key.name === "constructor" || key.type === "Literal" && key.value === "constructor")) { - if (hadConstructor) this.raise(key.start, "Duplicate constructor in the same class"); - if (isGetSet) this.raise(key.start, "Constructor can't have get/set modifier"); - if (isGenerator) this.raise(key.start, "Constructor can't be a generator"); - method.kind = "constructor"; - hadConstructor = true; - } - } - this.parseClassMethod(classBody, method, isGenerator); - if (isGetSet) { - var paramCount = method.kind === "get" ? 0 : 1; - if (method.value.params.length !== paramCount) { - var start = method.value.start; - if (method.kind === "get") this.raise(start, "getter should have no params");else this.raise(start, "setter should have exactly one param"); - } - if (method.kind === "set" && method.value.params[0].type === "RestElement") this.raise(method.value.params[0].start, "Setter cannot use rest params"); - } - } - node.body = this.finishNode(classBody, "ClassBody"); - return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression"); -}; - -pp.parseClassMethod = function (classBody, method, isGenerator) { - method.value = this.parseMethod(isGenerator); - classBody.body.push(this.finishNode(method, "MethodDefinition")); -}; - -pp.parseClassId = function (node, isStatement) { - node.id = this.type === _tokentype.types.name ? this.parseIdent() : isStatement ? this.unexpected() : null; -}; - -pp.parseClassSuper = function (node) { - node.superClass = this.eat(_tokentype.types._extends) ? this.parseExprSubscripts() : null; -}; - -// Parses module export declaration. - -pp.parseExport = function (node) { - this.next(); - // export * from '...' - if (this.eat(_tokentype.types.star)) { - this.expectContextual("from"); - node.source = this.type === _tokentype.types.string ? this.parseExprAtom() : this.unexpected(); - this.semicolon(); - return this.finishNode(node, "ExportAllDeclaration"); - } - if (this.eat(_tokentype.types._default)) { - // export default ... - var expr = this.parseMaybeAssign(); - var needsSemi = true; - if (expr.type == "FunctionExpression" || expr.type == "ClassExpression") { - needsSemi = false; - if (expr.id) { - expr.type = expr.type == "FunctionExpression" ? "FunctionDeclaration" : "ClassDeclaration"; - } - } - node.declaration = expr; - if (needsSemi) this.semicolon(); - return this.finishNode(node, "ExportDefaultDeclaration"); - } - // export var|const|let|function|class ... - if (this.shouldParseExportStatement()) { - node.declaration = this.parseStatement(true); - node.specifiers = []; - node.source = null; - } else { - // export { x, y as z } [from '...'] - node.declaration = null; - node.specifiers = this.parseExportSpecifiers(); - if (this.eatContextual("from")) { - node.source = this.type === _tokentype.types.string ? this.parseExprAtom() : this.unexpected(); - } else { - // check for keywords used as local names - for (var i = 0; i < node.specifiers.length; i++) { - if (this.keywords.test(node.specifiers[i].local.name) || this.reservedWords.test(node.specifiers[i].local.name)) { - this.unexpected(node.specifiers[i].local.start); - } - } - - node.source = null; - } - this.semicolon(); - } - return this.finishNode(node, "ExportNamedDeclaration"); -}; - -pp.shouldParseExportStatement = function () { - return this.type.keyword; -}; - -// Parses a comma-separated list of module exports. - -pp.parseExportSpecifiers = function () { - var nodes = [], - first = true; - // export { x, y as z } [from '...'] - this.expect(_tokentype.types.braceL); - while (!this.eat(_tokentype.types.braceR)) { - if (!first) { - this.expect(_tokentype.types.comma); - if (this.afterTrailingComma(_tokentype.types.braceR)) break; - } else first = false; - - var node = this.startNode(); - node.local = this.parseIdent(this.type === _tokentype.types._default); - node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local; - nodes.push(this.finishNode(node, "ExportSpecifier")); - } - return nodes; -}; - -// Parses import declaration. - -pp.parseImport = function (node) { - this.next(); - // import '...' - if (this.type === _tokentype.types.string) { - node.specifiers = empty; - node.source = this.parseExprAtom(); - } else { - node.specifiers = this.parseImportSpecifiers(); - this.expectContextual("from"); - node.source = this.type === _tokentype.types.string ? this.parseExprAtom() : this.unexpected(); - } - this.semicolon(); - return this.finishNode(node, "ImportDeclaration"); -}; - -// Parses a comma-separated list of module imports. - -pp.parseImportSpecifiers = function () { - var nodes = [], - first = true; - if (this.type === _tokentype.types.name) { - // import defaultObj, { x, y as z } from '...' - var node = this.startNode(); - node.local = this.parseIdent(); - this.checkLVal(node.local, true); - nodes.push(this.finishNode(node, "ImportDefaultSpecifier")); - if (!this.eat(_tokentype.types.comma)) return nodes; - } - if (this.type === _tokentype.types.star) { - var node = this.startNode(); - this.next(); - this.expectContextual("as"); - node.local = this.parseIdent(); - this.checkLVal(node.local, true); - nodes.push(this.finishNode(node, "ImportNamespaceSpecifier")); - return nodes; - } - this.expect(_tokentype.types.braceL); - while (!this.eat(_tokentype.types.braceR)) { - if (!first) { - this.expect(_tokentype.types.comma); - if (this.afterTrailingComma(_tokentype.types.braceR)) break; - } else first = false; - - var node = this.startNode(); - node.imported = this.parseIdent(true); - if (this.eatContextual("as")) { - node.local = this.parseIdent(); - } else { - node.local = node.imported; - if (this.isKeyword(node.local.name)) this.unexpected(node.local.start); - if (this.reservedWordsStrict.test(node.local.name)) this.raise(node.local.start, "The keyword '" + node.local.name + "' is reserved"); - } - this.checkLVal(node.local, true); - nodes.push(this.finishNode(node, "ImportSpecifier")); - } - return nodes; -}; - -},{"./state":10,"./tokentype":14,"./whitespace":16}],12:[function(_dereq_,module,exports){ -// The algorithm used to determine whether a regexp can appear at a -// given point in the program is loosely based on sweet.js' approach. -// See https://github.com/mozilla/sweet.js/wiki/design - -"use strict"; - -exports.__esModule = true; - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var _state = _dereq_("./state"); - -var _tokentype = _dereq_("./tokentype"); - -var _whitespace = _dereq_("./whitespace"); - -var TokContext = function TokContext(token, isExpr, preserveSpace, override) { - _classCallCheck(this, TokContext); - - this.token = token; - this.isExpr = !!isExpr; - this.preserveSpace = !!preserveSpace; - this.override = override; -}; - -exports.TokContext = TokContext; -var types = { - b_stat: new TokContext("{", false), - b_expr: new TokContext("{", true), - b_tmpl: new TokContext("${", true), - p_stat: new TokContext("(", false), - p_expr: new TokContext("(", true), - q_tmpl: new TokContext("`", true, true, function (p) { - return p.readTmplToken(); - }), - f_expr: new TokContext("function", true) -}; - -exports.types = types; -var pp = _state.Parser.prototype; - -pp.initialContext = function () { - return [types.b_stat]; -}; - -pp.braceIsBlock = function (prevType) { - if (prevType === _tokentype.types.colon) { - var _parent = this.curContext(); - if (_parent === types.b_stat || _parent === types.b_expr) return !_parent.isExpr; - } - if (prevType === _tokentype.types._return) return _whitespace.lineBreak.test(this.input.slice(this.lastTokEnd, this.start)); - if (prevType === _tokentype.types._else || prevType === _tokentype.types.semi || prevType === _tokentype.types.eof || prevType === _tokentype.types.parenR) return true; - if (prevType == _tokentype.types.braceL) return this.curContext() === types.b_stat; - return !this.exprAllowed; -}; - -pp.updateContext = function (prevType) { - var update = undefined, - type = this.type; - if (type.keyword && prevType == _tokentype.types.dot) this.exprAllowed = false;else if (update = type.updateContext) update.call(this, prevType);else this.exprAllowed = type.beforeExpr; -}; - -// Token-specific context update code - -_tokentype.types.parenR.updateContext = _tokentype.types.braceR.updateContext = function () { - if (this.context.length == 1) { - this.exprAllowed = true; - return; - } - var out = this.context.pop(); - if (out === types.b_stat && this.curContext() === types.f_expr) { - this.context.pop(); - this.exprAllowed = false; - } else if (out === types.b_tmpl) { - this.exprAllowed = true; - } else { - this.exprAllowed = !out.isExpr; - } -}; - -_tokentype.types.braceL.updateContext = function (prevType) { - this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr); - this.exprAllowed = true; -}; - -_tokentype.types.dollarBraceL.updateContext = function () { - this.context.push(types.b_tmpl); - this.exprAllowed = true; -}; - -_tokentype.types.parenL.updateContext = function (prevType) { - var statementParens = prevType === _tokentype.types._if || prevType === _tokentype.types._for || prevType === _tokentype.types._with || prevType === _tokentype.types._while; - this.context.push(statementParens ? types.p_stat : types.p_expr); - this.exprAllowed = true; -}; - -_tokentype.types.incDec.updateContext = function () { - // tokExprAllowed stays unchanged -}; - -_tokentype.types._function.updateContext = function () { - if (this.curContext() !== types.b_stat) this.context.push(types.f_expr); - this.exprAllowed = false; -}; - -_tokentype.types.backQuote.updateContext = function () { - if (this.curContext() === types.q_tmpl) this.context.pop();else this.context.push(types.q_tmpl); - this.exprAllowed = false; -}; - -},{"./state":10,"./tokentype":14,"./whitespace":16}],13:[function(_dereq_,module,exports){ -"use strict"; - -exports.__esModule = true; - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var _identifier = _dereq_("./identifier"); - -var _tokentype = _dereq_("./tokentype"); - -var _state = _dereq_("./state"); - -var _locutil = _dereq_("./locutil"); - -var _whitespace = _dereq_("./whitespace"); - -// Object type used to represent tokens. Note that normally, tokens -// simply exist as properties on the parser object. This is only -// used for the onToken callback and the external tokenizer. - -var Token = function Token(p) { - _classCallCheck(this, Token); - - this.type = p.type; - this.value = p.value; - this.start = p.start; - this.end = p.end; - if (p.options.locations) this.loc = new _locutil.SourceLocation(p, p.startLoc, p.endLoc); - if (p.options.ranges) this.range = [p.start, p.end]; -} - -// ## Tokenizer - -; - -exports.Token = Token; -var pp = _state.Parser.prototype; - -// Are we running under Rhino? -var isRhino = typeof Packages == "object" && Object.prototype.toString.call(Packages) == "[object JavaPackage]"; - -// Move to the next token - -pp.next = function () { - if (this.options.onToken) this.options.onToken(new Token(this)); - - this.lastTokEnd = this.end; - this.lastTokStart = this.start; - this.lastTokEndLoc = this.endLoc; - this.lastTokStartLoc = this.startLoc; - this.nextToken(); -}; - -pp.getToken = function () { - this.next(); - return new Token(this); -}; - -// If we're in an ES6 environment, make parsers iterable -if (typeof Symbol !== "undefined") pp[Symbol.iterator] = function () { - var self = this; - return { next: function next() { - var token = self.getToken(); - return { - done: token.type === _tokentype.types.eof, - value: token - }; - } }; -}; - -// Toggle strict mode. Re-reads the next number or string to please -// pedantic tests (`"use strict"; 010;` should fail). - -pp.setStrict = function (strict) { - this.strict = strict; - if (this.type !== _tokentype.types.num && this.type !== _tokentype.types.string) return; - this.pos = this.start; - if (this.options.locations) { - while (this.pos < this.lineStart) { - this.lineStart = this.input.lastIndexOf("\n", this.lineStart - 2) + 1; - --this.curLine; - } - } - this.nextToken(); -}; - -pp.curContext = function () { - return this.context[this.context.length - 1]; -}; - -// Read a single token, updating the parser object's token-related -// properties. - -pp.nextToken = function () { - var curContext = this.curContext(); - if (!curContext || !curContext.preserveSpace) this.skipSpace(); - - this.start = this.pos; - if (this.options.locations) this.startLoc = this.curPosition(); - if (this.pos >= this.input.length) return this.finishToken(_tokentype.types.eof); - - if (curContext.override) return curContext.override(this);else this.readToken(this.fullCharCodeAtPos()); -}; - -pp.readToken = function (code) { - // Identifier or keyword. '\uXXXX' sequences are allowed in - // identifiers, so '\' also dispatches to that. - if (_identifier.isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) return this.readWord(); - - return this.getTokenFromCode(code); -}; - -pp.fullCharCodeAtPos = function () { - var code = this.input.charCodeAt(this.pos); - if (code <= 0xd7ff || code >= 0xe000) return code; - var next = this.input.charCodeAt(this.pos + 1); - return (code << 10) + next - 0x35fdc00; -}; - -pp.skipBlockComment = function () { - var startLoc = this.options.onComment && this.curPosition(); - var start = this.pos, - end = this.input.indexOf("*/", this.pos += 2); - if (end === -1) this.raise(this.pos - 2, "Unterminated comment"); - this.pos = end + 2; - if (this.options.locations) { - _whitespace.lineBreakG.lastIndex = start; - var match = undefined; - while ((match = _whitespace.lineBreakG.exec(this.input)) && match.index < this.pos) { - ++this.curLine; - this.lineStart = match.index + match[0].length; - } - } - if (this.options.onComment) this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, startLoc, this.curPosition()); -}; - -pp.skipLineComment = function (startSkip) { - var start = this.pos; - var startLoc = this.options.onComment && this.curPosition(); - var ch = this.input.charCodeAt(this.pos += startSkip); - while (this.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { - ++this.pos; - ch = this.input.charCodeAt(this.pos); - } - if (this.options.onComment) this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, startLoc, this.curPosition()); -}; - -// Called at the start of the parse and after every token. Skips -// whitespace and comments, and. - -pp.skipSpace = function () { - loop: while (this.pos < this.input.length) { - var ch = this.input.charCodeAt(this.pos); - switch (ch) { - case 32:case 160: - // ' ' - ++this.pos; - break; - case 13: - if (this.input.charCodeAt(this.pos + 1) === 10) { - ++this.pos; - } - case 10:case 8232:case 8233: - ++this.pos; - if (this.options.locations) { - ++this.curLine; - this.lineStart = this.pos; - } - break; - case 47: - // '/' - switch (this.input.charCodeAt(this.pos + 1)) { - case 42: - // '*' - this.skipBlockComment(); - break; - case 47: - this.skipLineComment(2); - break; - default: - break loop; - } - break; - default: - if (ch > 8 && ch < 14 || ch >= 5760 && _whitespace.nonASCIIwhitespace.test(String.fromCharCode(ch))) { - ++this.pos; - } else { - break loop; - } - } - } -}; - -// Called at the end of every token. Sets `end`, `val`, and -// maintains `context` and `exprAllowed`, and skips the space after -// the token, so that the next one's `start` will point at the -// right position. - -pp.finishToken = function (type, val) { - this.end = this.pos; - if (this.options.locations) this.endLoc = this.curPosition(); - var prevType = this.type; - this.type = type; - this.value = val; - - this.updateContext(prevType); -}; - -// ### Token reading - -// This is the function that is called to fetch the next token. It -// is somewhat obscure, because it works in character codes rather -// than characters, and because operator parsing has been inlined -// into it. -// -// All in the name of speed. -// -pp.readToken_dot = function () { - var next = this.input.charCodeAt(this.pos + 1); - if (next >= 48 && next <= 57) return this.readNumber(true); - var next2 = this.input.charCodeAt(this.pos + 2); - if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { - // 46 = dot '.' - this.pos += 3; - return this.finishToken(_tokentype.types.ellipsis); - } else { - ++this.pos; - return this.finishToken(_tokentype.types.dot); - } -}; - -pp.readToken_slash = function () { - // '/' - var next = this.input.charCodeAt(this.pos + 1); - if (this.exprAllowed) { - ++this.pos;return this.readRegexp(); - } - if (next === 61) return this.finishOp(_tokentype.types.assign, 2); - return this.finishOp(_tokentype.types.slash, 1); -}; - -pp.readToken_mult_modulo = function (code) { - // '%*' - var next = this.input.charCodeAt(this.pos + 1); - if (next === 61) return this.finishOp(_tokentype.types.assign, 2); - return this.finishOp(code === 42 ? _tokentype.types.star : _tokentype.types.modulo, 1); -}; - -pp.readToken_pipe_amp = function (code) { - // '|&' - var next = this.input.charCodeAt(this.pos + 1); - if (next === code) return this.finishOp(code === 124 ? _tokentype.types.logicalOR : _tokentype.types.logicalAND, 2); - if (next === 61) return this.finishOp(_tokentype.types.assign, 2); - return this.finishOp(code === 124 ? _tokentype.types.bitwiseOR : _tokentype.types.bitwiseAND, 1); -}; - -pp.readToken_caret = function () { - // '^' - var next = this.input.charCodeAt(this.pos + 1); - if (next === 61) return this.finishOp(_tokentype.types.assign, 2); - return this.finishOp(_tokentype.types.bitwiseXOR, 1); -}; - -pp.readToken_plus_min = function (code) { - // '+-' - var next = this.input.charCodeAt(this.pos + 1); - if (next === code) { - if (next == 45 && this.input.charCodeAt(this.pos + 2) == 62 && _whitespace.lineBreak.test(this.input.slice(this.lastTokEnd, this.pos))) { - // A `-->` line comment - this.skipLineComment(3); - this.skipSpace(); - return this.nextToken(); - } - return this.finishOp(_tokentype.types.incDec, 2); - } - if (next === 61) return this.finishOp(_tokentype.types.assign, 2); - return this.finishOp(_tokentype.types.plusMin, 1); -}; - -pp.readToken_lt_gt = function (code) { - // '<>' - var next = this.input.charCodeAt(this.pos + 1); - var size = 1; - if (next === code) { - size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; - if (this.input.charCodeAt(this.pos + size) === 61) return this.finishOp(_tokentype.types.assign, size + 1); - return this.finishOp(_tokentype.types.bitShift, size); - } - if (next == 33 && code == 60 && this.input.charCodeAt(this.pos + 2) == 45 && this.input.charCodeAt(this.pos + 3) == 45) { - if (this.inModule) this.unexpected(); - // `` line comment - this.skipLineComment(3) - this.skipSpace() - return this.nextToken() - } - return this.finishOp(tt.incDec, 2) - } - if (next === 61) return this.finishOp(tt.assign, 2) - return this.finishOp(tt.plusMin, 1) -} - -pp.readToken_lt_gt = function(code) { // '<>' - let next = this.input.charCodeAt(this.pos + 1) - let size = 1 - if (next === code) { - size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2 - if (this.input.charCodeAt(this.pos + size) === 61) return this.finishOp(tt.assign, size + 1) - return this.finishOp(tt.bitShift, size) - } - if (next == 33 && code == 60 && this.input.charCodeAt(this.pos + 2) == 45 && - this.input.charCodeAt(this.pos + 3) == 45) { - if (this.inModule) this.unexpected() - // ` - -AsyncKit provides harness for `parallel` and `serial` iterators over list of items represented by arrays or objects. -Optionally it accepts abort function (should be synchronously return by iterator for each item), and terminates left over jobs upon an error event. For specific iteration order built-in (`ascending` and `descending`) and custom sort helpers also supported, via `asynckit.serialOrdered` method. - -It ensures async operations to keep behavior more stable and prevent `Maximum call stack size exceeded` errors, from sync iterators. - -| compression | size | -| :----------------- | -------: | -| asynckit.js | 12.34 kB | -| asynckit.min.js | 4.11 kB | -| asynckit.min.js.gz | 1.47 kB | - - -## Install - -```sh -$ npm install --save asynckit -``` - -## Examples - -### Parallel Jobs - -Runs iterator over provided array in parallel. Stores output in the `result` array, -on the matching positions. In unlikely event of an error from one of the jobs, -will terminate rest of the active jobs (if abort function is provided) -and return error along with salvaged data to the main callback function. - -#### Input Array - -```javascript -var parallel = require('asynckit').parallel - , assert = require('assert') - ; - -var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ] - , expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ] - , expectedTarget = [ 1, 1, 2, 4, 8, 16, 32, 64 ] - , target = [] - ; - -parallel(source, asyncJob, function(err, result) -{ - assert.deepEqual(result, expectedResult); - assert.deepEqual(target, expectedTarget); -}); - -// async job accepts one element from the array -// and a callback function -function asyncJob(item, cb) -{ - // different delays (in ms) per item - var delay = item * 25; - - // pretend different jobs take different time to finish - // and not in consequential order - var timeoutId = setTimeout(function() { - target.push(item); - cb(null, item * 2); - }, delay); - - // allow to cancel "leftover" jobs upon error - // return function, invoking of which will abort this job - return clearTimeout.bind(null, timeoutId); -} -``` - -More examples could be found in [test/test-parallel-array.js](test/test-parallel-array.js). - -#### Input Object - -Also it supports named jobs, listed via object. - -```javascript -var parallel = require('asynckit/parallel') - , assert = require('assert') - ; - -var source = { first: 1, one: 1, four: 4, sixteen: 16, sixtyFour: 64, thirtyTwo: 32, eight: 8, two: 2 } - , expectedResult = { first: 2, one: 2, four: 8, sixteen: 32, sixtyFour: 128, thirtyTwo: 64, eight: 16, two: 4 } - , expectedTarget = [ 1, 1, 2, 4, 8, 16, 32, 64 ] - , expectedKeys = [ 'first', 'one', 'two', 'four', 'eight', 'sixteen', 'thirtyTwo', 'sixtyFour' ] - , target = [] - , keys = [] - ; - -parallel(source, asyncJob, function(err, result) -{ - assert.deepEqual(result, expectedResult); - assert.deepEqual(target, expectedTarget); - assert.deepEqual(keys, expectedKeys); -}); - -// supports full value, key, callback (shortcut) interface -function asyncJob(item, key, cb) -{ - // different delays (in ms) per item - var delay = item * 25; - - // pretend different jobs take different time to finish - // and not in consequential order - var timeoutId = setTimeout(function() { - keys.push(key); - target.push(item); - cb(null, item * 2); - }, delay); - - // allow to cancel "leftover" jobs upon error - // return function, invoking of which will abort this job - return clearTimeout.bind(null, timeoutId); -} -``` - -More examples could be found in [test/test-parallel-object.js](test/test-parallel-object.js). - -### Serial Jobs - -Runs iterator over provided array sequentially. Stores output in the `result` array, -on the matching positions. In unlikely event of an error from one of the jobs, -will not proceed to the rest of the items in the list -and return error along with salvaged data to the main callback function. - -#### Input Array - -```javascript -var serial = require('asynckit/serial') - , assert = require('assert') - ; - -var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ] - , expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ] - , expectedTarget = [ 0, 1, 2, 3, 4, 5, 6, 7 ] - , target = [] - ; - -serial(source, asyncJob, function(err, result) -{ - assert.deepEqual(result, expectedResult); - assert.deepEqual(target, expectedTarget); -}); - -// extended interface (item, key, callback) -// also supported for arrays -function asyncJob(item, key, cb) -{ - target.push(key); - - // it will be automatically made async - // even it iterator "returns" in the same event loop - cb(null, item * 2); -} -``` - -More examples could be found in [test/test-serial-array.js](test/test-serial-array.js). - -#### Input Object - -Also it supports named jobs, listed via object. - -```javascript -var serial = require('asynckit').serial - , assert = require('assert') - ; - -var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ] - , expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ] - , expectedTarget = [ 0, 1, 2, 3, 4, 5, 6, 7 ] - , target = [] - ; - -var source = { first: 1, one: 1, four: 4, sixteen: 16, sixtyFour: 64, thirtyTwo: 32, eight: 8, two: 2 } - , expectedResult = { first: 2, one: 2, four: 8, sixteen: 32, sixtyFour: 128, thirtyTwo: 64, eight: 16, two: 4 } - , expectedTarget = [ 1, 1, 4, 16, 64, 32, 8, 2 ] - , target = [] - ; - - -serial(source, asyncJob, function(err, result) -{ - assert.deepEqual(result, expectedResult); - assert.deepEqual(target, expectedTarget); -}); - -// shortcut interface (item, callback) -// works for object as well as for the arrays -function asyncJob(item, cb) -{ - target.push(item); - - // it will be automatically made async - // even it iterator "returns" in the same event loop - cb(null, item * 2); -} -``` - -More examples could be found in [test/test-serial-object.js](test/test-serial-object.js). - -_Note: Since _object_ is an _unordered_ collection of properties, -it may produce unexpected results with sequential iterations. -Whenever order of the jobs' execution is important please use `serialOrdered` method._ - -### Ordered Serial Iterations - -TBD - -For example [compare-property](compare-property) package. - -### Streaming interface - -TBD - -## Want to Know More? - -More examples can be found in [test folder](test/). - -Or open an [issue](https://github.com/alexindigo/asynckit/issues) with questions and/or suggestions. - -## License - -AsyncKit is licensed under the MIT license. diff --git a/web/node_modules/asynckit/bench.js b/web/node_modules/asynckit/bench.js deleted file mode 100644 index c612f1a..0000000 --- a/web/node_modules/asynckit/bench.js +++ /dev/null @@ -1,76 +0,0 @@ -/* eslint no-console: "off" */ - -var asynckit = require('./') - , async = require('async') - , assert = require('assert') - , expected = 0 - ; - -var Benchmark = require('benchmark'); -var suite = new Benchmark.Suite; - -var source = []; -for (var z = 1; z < 100; z++) -{ - source.push(z); - expected += z; -} - -suite -// add tests - -.add('async.map', function(deferred) -{ - var total = 0; - - async.map(source, - function(i, cb) - { - setImmediate(function() - { - total += i; - cb(null, total); - }); - }, - function(err, result) - { - assert.ifError(err); - assert.equal(result[result.length - 1], expected); - deferred.resolve(); - }); -}, {'defer': true}) - - -.add('asynckit.parallel', function(deferred) -{ - var total = 0; - - asynckit.parallel(source, - function(i, cb) - { - setImmediate(function() - { - total += i; - cb(null, total); - }); - }, - function(err, result) - { - assert.ifError(err); - assert.equal(result[result.length - 1], expected); - deferred.resolve(); - }); -}, {'defer': true}) - - -// add listeners -.on('cycle', function(ev) -{ - console.log(String(ev.target)); -}) -.on('complete', function() -{ - console.log('Fastest is ' + this.filter('fastest').map('name')); -}) -// run async -.run({ 'async': true }); diff --git a/web/node_modules/asynckit/index.js b/web/node_modules/asynckit/index.js deleted file mode 100644 index 455f945..0000000 --- a/web/node_modules/asynckit/index.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = -{ - parallel : require('./parallel.js'), - serial : require('./serial.js'), - serialOrdered : require('./serialOrdered.js') -}; diff --git a/web/node_modules/asynckit/lib/abort.js b/web/node_modules/asynckit/lib/abort.js deleted file mode 100644 index 114367e..0000000 --- a/web/node_modules/asynckit/lib/abort.js +++ /dev/null @@ -1,29 +0,0 @@ -// API -module.exports = abort; - -/** - * Aborts leftover active jobs - * - * @param {object} state - current state object - */ -function abort(state) -{ - Object.keys(state.jobs).forEach(clean.bind(state)); - - // reset leftover jobs - state.jobs = {}; -} - -/** - * Cleans up leftover job by invoking abort function for the provided job id - * - * @this state - * @param {string|number} key - job id to abort - */ -function clean(key) -{ - if (typeof this.jobs[key] == 'function') - { - this.jobs[key](); - } -} diff --git a/web/node_modules/asynckit/lib/async.js b/web/node_modules/asynckit/lib/async.js deleted file mode 100644 index 7f1288a..0000000 --- a/web/node_modules/asynckit/lib/async.js +++ /dev/null @@ -1,34 +0,0 @@ -var defer = require('./defer.js'); - -// API -module.exports = async; - -/** - * Runs provided callback asynchronously - * even if callback itself is not - * - * @param {function} callback - callback to invoke - * @returns {function} - augmented callback - */ -function async(callback) -{ - var isAsync = false; - - // check if async happened - defer(function() { isAsync = true; }); - - return function async_callback(err, result) - { - if (isAsync) - { - callback(err, result); - } - else - { - defer(function nextTick_callback() - { - callback(err, result); - }); - } - }; -} diff --git a/web/node_modules/asynckit/lib/defer.js b/web/node_modules/asynckit/lib/defer.js deleted file mode 100644 index b67110c..0000000 --- a/web/node_modules/asynckit/lib/defer.js +++ /dev/null @@ -1,26 +0,0 @@ -module.exports = defer; - -/** - * Runs provided function on next iteration of the event loop - * - * @param {function} fn - function to run - */ -function defer(fn) -{ - var nextTick = typeof setImmediate == 'function' - ? setImmediate - : ( - typeof process == 'object' && typeof process.nextTick == 'function' - ? process.nextTick - : null - ); - - if (nextTick) - { - nextTick(fn); - } - else - { - setTimeout(fn, 0); - } -} diff --git a/web/node_modules/asynckit/lib/iterate.js b/web/node_modules/asynckit/lib/iterate.js deleted file mode 100644 index 5d2839a..0000000 --- a/web/node_modules/asynckit/lib/iterate.js +++ /dev/null @@ -1,75 +0,0 @@ -var async = require('./async.js') - , abort = require('./abort.js') - ; - -// API -module.exports = iterate; - -/** - * Iterates over each job object - * - * @param {array|object} list - array or object (named list) to iterate over - * @param {function} iterator - iterator to run - * @param {object} state - current job status - * @param {function} callback - invoked when all elements processed - */ -function iterate(list, iterator, state, callback) -{ - // store current index - var key = state['keyedList'] ? state['keyedList'][state.index] : state.index; - - state.jobs[key] = runJob(iterator, key, list[key], function(error, output) - { - // don't repeat yourself - // skip secondary callbacks - if (!(key in state.jobs)) - { - return; - } - - // clean up jobs - delete state.jobs[key]; - - if (error) - { - // don't process rest of the results - // stop still active jobs - // and reset the list - abort(state); - } - else - { - state.results[key] = output; - } - - // return salvaged results - callback(error, state.results); - }); -} - -/** - * Runs iterator over provided job element - * - * @param {function} iterator - iterator to invoke - * @param {string|number} key - key/index of the element in the list of jobs - * @param {mixed} item - job description - * @param {function} callback - invoked after iterator is done with the job - * @returns {function|mixed} - job abort function or something else - */ -function runJob(iterator, key, item, callback) -{ - var aborter; - - // allow shortcut if iterator expects only two arguments - if (iterator.length == 2) - { - aborter = iterator(item, async(callback)); - } - // otherwise go with full three arguments - else - { - aborter = iterator(item, key, async(callback)); - } - - return aborter; -} diff --git a/web/node_modules/asynckit/lib/readable_asynckit.js b/web/node_modules/asynckit/lib/readable_asynckit.js deleted file mode 100644 index 78ad240..0000000 --- a/web/node_modules/asynckit/lib/readable_asynckit.js +++ /dev/null @@ -1,91 +0,0 @@ -var streamify = require('./streamify.js') - , defer = require('./defer.js') - ; - -// API -module.exports = ReadableAsyncKit; - -/** - * Base constructor for all streams - * used to hold properties/methods - */ -function ReadableAsyncKit() -{ - ReadableAsyncKit.super_.apply(this, arguments); - - // list of active jobs - this.jobs = {}; - - // add stream methods - this.destroy = destroy; - this._start = _start; - this._read = _read; -} - -/** - * Destroys readable stream, - * by aborting outstanding jobs - * - * @returns {void} - */ -function destroy() -{ - if (this.destroyed) - { - return; - } - - this.destroyed = true; - - if (typeof this.terminator == 'function') - { - this.terminator(); - } -} - -/** - * Starts provided jobs in async manner - * - * @private - */ -function _start() -{ - // first argument – runner function - var runner = arguments[0] - // take away first argument - , args = Array.prototype.slice.call(arguments, 1) - // second argument - input data - , input = args[0] - // last argument - result callback - , endCb = streamify.callback.call(this, args[args.length - 1]) - ; - - args[args.length - 1] = endCb; - // third argument - iterator - args[1] = streamify.iterator.call(this, args[1]); - - // allow time for proper setup - defer(function() - { - if (!this.destroyed) - { - this.terminator = runner.apply(null, args); - } - else - { - endCb(null, Array.isArray(input) ? [] : {}); - } - }.bind(this)); -} - - -/** - * Implement _read to comply with Readable streams - * Doesn't really make sense for flowing object mode - * - * @private - */ -function _read() -{ - -} diff --git a/web/node_modules/asynckit/lib/readable_parallel.js b/web/node_modules/asynckit/lib/readable_parallel.js deleted file mode 100644 index 5d2929f..0000000 --- a/web/node_modules/asynckit/lib/readable_parallel.js +++ /dev/null @@ -1,25 +0,0 @@ -var parallel = require('../parallel.js'); - -// API -module.exports = ReadableParallel; - -/** - * Streaming wrapper to `asynckit.parallel` - * - * @param {array|object} list - array or object (named list) to iterate over - * @param {function} iterator - iterator to run - * @param {function} callback - invoked when all elements processed - * @returns {stream.Readable#} - */ -function ReadableParallel(list, iterator, callback) -{ - if (!(this instanceof ReadableParallel)) - { - return new ReadableParallel(list, iterator, callback); - } - - // turn on object mode - ReadableParallel.super_.call(this, {objectMode: true}); - - this._start(parallel, list, iterator, callback); -} diff --git a/web/node_modules/asynckit/lib/readable_serial.js b/web/node_modules/asynckit/lib/readable_serial.js deleted file mode 100644 index 7822698..0000000 --- a/web/node_modules/asynckit/lib/readable_serial.js +++ /dev/null @@ -1,25 +0,0 @@ -var serial = require('../serial.js'); - -// API -module.exports = ReadableSerial; - -/** - * Streaming wrapper to `asynckit.serial` - * - * @param {array|object} list - array or object (named list) to iterate over - * @param {function} iterator - iterator to run - * @param {function} callback - invoked when all elements processed - * @returns {stream.Readable#} - */ -function ReadableSerial(list, iterator, callback) -{ - if (!(this instanceof ReadableSerial)) - { - return new ReadableSerial(list, iterator, callback); - } - - // turn on object mode - ReadableSerial.super_.call(this, {objectMode: true}); - - this._start(serial, list, iterator, callback); -} diff --git a/web/node_modules/asynckit/lib/readable_serial_ordered.js b/web/node_modules/asynckit/lib/readable_serial_ordered.js deleted file mode 100644 index 3de89c4..0000000 --- a/web/node_modules/asynckit/lib/readable_serial_ordered.js +++ /dev/null @@ -1,29 +0,0 @@ -var serialOrdered = require('../serialOrdered.js'); - -// API -module.exports = ReadableSerialOrdered; -// expose sort helpers -module.exports.ascending = serialOrdered.ascending; -module.exports.descending = serialOrdered.descending; - -/** - * Streaming wrapper to `asynckit.serialOrdered` - * - * @param {array|object} list - array or object (named list) to iterate over - * @param {function} iterator - iterator to run - * @param {function} sortMethod - custom sort function - * @param {function} callback - invoked when all elements processed - * @returns {stream.Readable#} - */ -function ReadableSerialOrdered(list, iterator, sortMethod, callback) -{ - if (!(this instanceof ReadableSerialOrdered)) - { - return new ReadableSerialOrdered(list, iterator, sortMethod, callback); - } - - // turn on object mode - ReadableSerialOrdered.super_.call(this, {objectMode: true}); - - this._start(serialOrdered, list, iterator, sortMethod, callback); -} diff --git a/web/node_modules/asynckit/lib/state.js b/web/node_modules/asynckit/lib/state.js deleted file mode 100644 index cbea7ad..0000000 --- a/web/node_modules/asynckit/lib/state.js +++ /dev/null @@ -1,37 +0,0 @@ -// API -module.exports = state; - -/** - * Creates initial state object - * for iteration over list - * - * @param {array|object} list - list to iterate over - * @param {function|null} sortMethod - function to use for keys sort, - * or `null` to keep them as is - * @returns {object} - initial state object - */ -function state(list, sortMethod) -{ - var isNamedList = !Array.isArray(list) - , initState = - { - index : 0, - keyedList: isNamedList || sortMethod ? Object.keys(list) : null, - jobs : {}, - results : isNamedList ? {} : [], - size : isNamedList ? Object.keys(list).length : list.length - } - ; - - if (sortMethod) - { - // sort array keys based on it's values - // sort object's keys just on own merit - initState.keyedList.sort(isNamedList ? sortMethod : function(a, b) - { - return sortMethod(list[a], list[b]); - }); - } - - return initState; -} diff --git a/web/node_modules/asynckit/lib/streamify.js b/web/node_modules/asynckit/lib/streamify.js deleted file mode 100644 index f56a1c9..0000000 --- a/web/node_modules/asynckit/lib/streamify.js +++ /dev/null @@ -1,141 +0,0 @@ -var async = require('./async.js'); - -// API -module.exports = { - iterator: wrapIterator, - callback: wrapCallback -}; - -/** - * Wraps iterators with long signature - * - * @this ReadableAsyncKit# - * @param {function} iterator - function to wrap - * @returns {function} - wrapped function - */ -function wrapIterator(iterator) -{ - var stream = this; - - return function(item, key, cb) - { - var aborter - , wrappedCb = async(wrapIteratorCallback.call(stream, cb, key)) - ; - - stream.jobs[key] = wrappedCb; - - // it's either shortcut (item, cb) - if (iterator.length == 2) - { - aborter = iterator(item, wrappedCb); - } - // or long format (item, key, cb) - else - { - aborter = iterator(item, key, wrappedCb); - } - - return aborter; - }; -} - -/** - * Wraps provided callback function - * allowing to execute snitch function before - * real callback - * - * @this ReadableAsyncKit# - * @param {function} callback - function to wrap - * @returns {function} - wrapped function - */ -function wrapCallback(callback) -{ - var stream = this; - - var wrapped = function(error, result) - { - return finisher.call(stream, error, result, callback); - }; - - return wrapped; -} - -/** - * Wraps provided iterator callback function - * makes sure snitch only called once, - * but passes secondary calls to the original callback - * - * @this ReadableAsyncKit# - * @param {function} callback - callback to wrap - * @param {number|string} key - iteration key - * @returns {function} wrapped callback - */ -function wrapIteratorCallback(callback, key) -{ - var stream = this; - - return function(error, output) - { - // don't repeat yourself - if (!(key in stream.jobs)) - { - callback(error, output); - return; - } - - // clean up jobs - delete stream.jobs[key]; - - return streamer.call(stream, error, {key: key, value: output}, callback); - }; -} - -/** - * Stream wrapper for iterator callback - * - * @this ReadableAsyncKit# - * @param {mixed} error - error response - * @param {mixed} output - iterator output - * @param {function} callback - callback that expects iterator results - */ -function streamer(error, output, callback) -{ - if (error && !this.error) - { - this.error = error; - this.pause(); - this.emit('error', error); - // send back value only, as expected - callback(error, output && output.value); - return; - } - - // stream stuff - this.push(output); - - // back to original track - // send back value only, as expected - callback(error, output && output.value); -} - -/** - * Stream wrapper for finishing callback - * - * @this ReadableAsyncKit# - * @param {mixed} error - error response - * @param {mixed} output - iterator output - * @param {function} callback - callback that expects final results - */ -function finisher(error, output, callback) -{ - // signal end of the stream - // only for successfully finished streams - if (!error) - { - this.push(null); - } - - // back to original track - callback(error, output); -} diff --git a/web/node_modules/asynckit/lib/terminator.js b/web/node_modules/asynckit/lib/terminator.js deleted file mode 100644 index d6eb992..0000000 --- a/web/node_modules/asynckit/lib/terminator.js +++ /dev/null @@ -1,29 +0,0 @@ -var abort = require('./abort.js') - , async = require('./async.js') - ; - -// API -module.exports = terminator; - -/** - * Terminates jobs in the attached state context - * - * @this AsyncKitState# - * @param {function} callback - final callback to invoke after termination - */ -function terminator(callback) -{ - if (!Object.keys(this.jobs).length) - { - return; - } - - // fast forward iteration index - this.index = this.size; - - // abort jobs - abort(this); - - // send back results we have so far - async(callback)(null, this.results); -} diff --git a/web/node_modules/asynckit/package.json b/web/node_modules/asynckit/package.json deleted file mode 100644 index c56f60a..0000000 --- a/web/node_modules/asynckit/package.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "_args": [ - [ - "asynckit@0.4.0", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "asynckit@0.4.0", - "_id": "asynckit@0.4.0", - "_inBundle": false, - "_integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "_location": "/asynckit", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "asynckit@0.4.0", - "name": "asynckit", - "escapedName": "asynckit", - "rawSpec": "0.4.0", - "saveSpec": null, - "fetchSpec": "0.4.0" - }, - "_requiredBy": [ - "/form-data" - ], - "_resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "_spec": "0.4.0", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "Alex Indigo", - "email": "iam@alexindigo.com" - }, - "bugs": { - "url": "https://github.com/alexindigo/asynckit/issues" - }, - "dependencies": {}, - "description": "Minimal async jobs utility library, with streams support", - "devDependencies": { - "browserify": "^13.0.0", - "browserify-istanbul": "^2.0.0", - "coveralls": "^2.11.9", - "eslint": "^2.9.0", - "istanbul": "^0.4.3", - "obake": "^0.1.2", - "phantomjs-prebuilt": "^2.1.7", - "pre-commit": "^1.1.3", - "reamde": "^1.1.0", - "rimraf": "^2.5.2", - "size-table": "^0.2.0", - "tap-spec": "^4.1.1", - "tape": "^4.5.1" - }, - "homepage": "https://github.com/alexindigo/asynckit#readme", - "keywords": [ - "async", - "jobs", - "parallel", - "serial", - "iterator", - "array", - "object", - "stream", - "destroy", - "terminate", - "abort" - ], - "license": "MIT", - "main": "index.js", - "name": "asynckit", - "pre-commit": [ - "clean", - "lint", - "test", - "browser", - "report", - "size" - ], - "repository": { - "type": "git", - "url": "git+https://github.com/alexindigo/asynckit.git" - }, - "scripts": { - "browser": "browserify -t browserify-istanbul test/lib/browserify_adjustment.js test/test-*.js | obake --coverage | tap-spec", - "clean": "rimraf coverage", - "debug": "tape test/test-*.js", - "lint": "eslint *.js lib/*.js test/*.js", - "report": "istanbul report", - "size": "browserify index.js | size-table asynckit", - "test": "istanbul cover --reporter=json tape -- 'test/test-*.js' | tap-spec", - "win-test": "tape test/test-*.js" - }, - "version": "0.4.0" -} diff --git a/web/node_modules/asynckit/parallel.js b/web/node_modules/asynckit/parallel.js deleted file mode 100644 index 3c50344..0000000 --- a/web/node_modules/asynckit/parallel.js +++ /dev/null @@ -1,43 +0,0 @@ -var iterate = require('./lib/iterate.js') - , initState = require('./lib/state.js') - , terminator = require('./lib/terminator.js') - ; - -// Public API -module.exports = parallel; - -/** - * Runs iterator over provided array elements in parallel - * - * @param {array|object} list - array or object (named list) to iterate over - * @param {function} iterator - iterator to run - * @param {function} callback - invoked when all elements processed - * @returns {function} - jobs terminator - */ -function parallel(list, iterator, callback) -{ - var state = initState(list); - - while (state.index < (state['keyedList'] || list).length) - { - iterate(list, iterator, state, function(error, result) - { - if (error) - { - callback(error, result); - return; - } - - // looks like it's the last one - if (Object.keys(state.jobs).length === 0) - { - callback(null, state.results); - return; - } - }); - - state.index++; - } - - return terminator.bind(state, callback); -} diff --git a/web/node_modules/asynckit/serial.js b/web/node_modules/asynckit/serial.js deleted file mode 100644 index 6cd949a..0000000 --- a/web/node_modules/asynckit/serial.js +++ /dev/null @@ -1,17 +0,0 @@ -var serialOrdered = require('./serialOrdered.js'); - -// Public API -module.exports = serial; - -/** - * Runs iterator over provided array elements in series - * - * @param {array|object} list - array or object (named list) to iterate over - * @param {function} iterator - iterator to run - * @param {function} callback - invoked when all elements processed - * @returns {function} - jobs terminator - */ -function serial(list, iterator, callback) -{ - return serialOrdered(list, iterator, null, callback); -} diff --git a/web/node_modules/asynckit/serialOrdered.js b/web/node_modules/asynckit/serialOrdered.js deleted file mode 100644 index 607eafe..0000000 --- a/web/node_modules/asynckit/serialOrdered.js +++ /dev/null @@ -1,75 +0,0 @@ -var iterate = require('./lib/iterate.js') - , initState = require('./lib/state.js') - , terminator = require('./lib/terminator.js') - ; - -// Public API -module.exports = serialOrdered; -// sorting helpers -module.exports.ascending = ascending; -module.exports.descending = descending; - -/** - * Runs iterator over provided sorted array elements in series - * - * @param {array|object} list - array or object (named list) to iterate over - * @param {function} iterator - iterator to run - * @param {function} sortMethod - custom sort function - * @param {function} callback - invoked when all elements processed - * @returns {function} - jobs terminator - */ -function serialOrdered(list, iterator, sortMethod, callback) -{ - var state = initState(list, sortMethod); - - iterate(list, iterator, state, function iteratorHandler(error, result) - { - if (error) - { - callback(error, result); - return; - } - - state.index++; - - // are we there yet? - if (state.index < (state['keyedList'] || list).length) - { - iterate(list, iterator, state, iteratorHandler); - return; - } - - // done here - callback(null, state.results); - }); - - return terminator.bind(state, callback); -} - -/* - * -- Sort methods - */ - -/** - * sort helper to sort array elements in ascending order - * - * @param {mixed} a - an item to compare - * @param {mixed} b - an item to compare - * @returns {number} - comparison result - */ -function ascending(a, b) -{ - return a < b ? -1 : a > b ? 1 : 0; -} - -/** - * sort helper to sort array elements in descending order - * - * @param {mixed} a - an item to compare - * @param {mixed} b - an item to compare - * @returns {number} - comparison result - */ -function descending(a, b) -{ - return -1 * ascending(a, b); -} diff --git a/web/node_modules/asynckit/stream.js b/web/node_modules/asynckit/stream.js deleted file mode 100644 index d43465f..0000000 --- a/web/node_modules/asynckit/stream.js +++ /dev/null @@ -1,21 +0,0 @@ -var inherits = require('util').inherits - , Readable = require('stream').Readable - , ReadableAsyncKit = require('./lib/readable_asynckit.js') - , ReadableParallel = require('./lib/readable_parallel.js') - , ReadableSerial = require('./lib/readable_serial.js') - , ReadableSerialOrdered = require('./lib/readable_serial_ordered.js') - ; - -// API -module.exports = -{ - parallel : ReadableParallel, - serial : ReadableSerial, - serialOrdered : ReadableSerialOrdered, -}; - -inherits(ReadableAsyncKit, Readable); - -inherits(ReadableParallel, ReadableAsyncKit); -inherits(ReadableSerial, ReadableAsyncKit); -inherits(ReadableSerialOrdered, ReadableAsyncKit); diff --git a/web/node_modules/aws-sign2/LICENSE b/web/node_modules/aws-sign2/LICENSE deleted file mode 100644 index a4a9aee..0000000 --- a/web/node_modules/aws-sign2/LICENSE +++ /dev/null @@ -1,55 +0,0 @@ -Apache License - -Version 2.0, January 2004 - -http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - -"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. - -"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. - -"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - -"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. - -"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. - -"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. - -"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). - -"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. - -"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." - -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: - -You must give any other recipients of the Work or Derivative Works a copy of this License; and - -You must cause any modified files to carry prominent notices stating that You changed the files; and - -You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and - -If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/web/node_modules/aws-sign2/README.md b/web/node_modules/aws-sign2/README.md deleted file mode 100644 index 763564e..0000000 --- a/web/node_modules/aws-sign2/README.md +++ /dev/null @@ -1,4 +0,0 @@ -aws-sign -======== - -AWS signing. Originally pulled from LearnBoost/knox, maintained as vendor in request, now a standalone module. diff --git a/web/node_modules/aws-sign2/index.js b/web/node_modules/aws-sign2/index.js deleted file mode 100644 index ac72093..0000000 --- a/web/node_modules/aws-sign2/index.js +++ /dev/null @@ -1,212 +0,0 @@ - -/*! - * Copyright 2010 LearnBoost - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Module dependencies. - */ - -var crypto = require('crypto') - , parse = require('url').parse - ; - -/** - * Valid keys. - */ - -var keys = - [ 'acl' - , 'location' - , 'logging' - , 'notification' - , 'partNumber' - , 'policy' - , 'requestPayment' - , 'torrent' - , 'uploadId' - , 'uploads' - , 'versionId' - , 'versioning' - , 'versions' - , 'website' - ] - -/** - * Return an "Authorization" header value with the given `options` - * in the form of "AWS :" - * - * @param {Object} options - * @return {String} - * @api private - */ - -function authorization (options) { - return 'AWS ' + options.key + ':' + sign(options) -} - -module.exports = authorization -module.exports.authorization = authorization - -/** - * Simple HMAC-SHA1 Wrapper - * - * @param {Object} options - * @return {String} - * @api private - */ - -function hmacSha1 (options) { - return crypto.createHmac('sha1', options.secret).update(options.message).digest('base64') -} - -module.exports.hmacSha1 = hmacSha1 - -/** - * Create a base64 sha1 HMAC for `options`. - * - * @param {Object} options - * @return {String} - * @api private - */ - -function sign (options) { - options.message = stringToSign(options) - return hmacSha1(options) -} -module.exports.sign = sign - -/** - * Create a base64 sha1 HMAC for `options`. - * - * Specifically to be used with S3 presigned URLs - * - * @param {Object} options - * @return {String} - * @api private - */ - -function signQuery (options) { - options.message = queryStringToSign(options) - return hmacSha1(options) -} -module.exports.signQuery= signQuery - -/** - * Return a string for sign() with the given `options`. - * - * Spec: - * - * \n - * \n - * \n - * \n - * [headers\n] - * - * - * @param {Object} options - * @return {String} - * @api private - */ - -function stringToSign (options) { - var headers = options.amazonHeaders || '' - if (headers) headers += '\n' - var r = - [ options.verb - , options.md5 - , options.contentType - , options.date ? options.date.toUTCString() : '' - , headers + options.resource - ] - return r.join('\n') -} -module.exports.queryStringToSign = stringToSign - -/** - * Return a string for sign() with the given `options`, but is meant exclusively - * for S3 presigned URLs - * - * Spec: - * - * \n - * - * - * @param {Object} options - * @return {String} - * @api private - */ - -function queryStringToSign (options){ - return 'GET\n\n\n' + options.date + '\n' + options.resource -} -module.exports.queryStringToSign = queryStringToSign - -/** - * Perform the following: - * - * - ignore non-amazon headers - * - lowercase fields - * - sort lexicographically - * - trim whitespace between ":" - * - join with newline - * - * @param {Object} headers - * @return {String} - * @api private - */ - -function canonicalizeHeaders (headers) { - var buf = [] - , fields = Object.keys(headers) - ; - for (var i = 0, len = fields.length; i < len; ++i) { - var field = fields[i] - , val = headers[field] - , field = field.toLowerCase() - ; - if (0 !== field.indexOf('x-amz')) continue - buf.push(field + ':' + val) - } - return buf.sort().join('\n') -} -module.exports.canonicalizeHeaders = canonicalizeHeaders - -/** - * Perform the following: - * - * - ignore non sub-resources - * - sort lexicographically - * - * @param {String} resource - * @return {String} - * @api private - */ - -function canonicalizeResource (resource) { - var url = parse(resource, true) - , path = url.pathname - , buf = [] - ; - - Object.keys(url.query).forEach(function(key){ - if (!~keys.indexOf(key)) return - var val = '' == url.query[key] ? '' : '=' + encodeURIComponent(url.query[key]) - buf.push(key + val) - }) - - return path + (buf.length ? '?' + buf.sort().join('&') : '') -} -module.exports.canonicalizeResource = canonicalizeResource diff --git a/web/node_modules/aws-sign2/package.json b/web/node_modules/aws-sign2/package.json deleted file mode 100644 index 1be3c2c..0000000 --- a/web/node_modules/aws-sign2/package.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "_args": [ - [ - "aws-sign2@0.6.0", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "aws-sign2@0.6.0", - "_id": "aws-sign2@0.6.0", - "_inBundle": false, - "_integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "_location": "/aws-sign2", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "aws-sign2@0.6.0", - "name": "aws-sign2", - "escapedName": "aws-sign2", - "rawSpec": "0.6.0", - "saveSpec": null, - "fetchSpec": "0.6.0" - }, - "_requiredBy": [ - "/request" - ], - "_resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "_spec": "0.6.0", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "Mikeal Rogers", - "email": "mikeal.rogers@gmail.com", - "url": "http://www.futurealoof.com" - }, - "bugs": { - "url": "https://github.com/mikeal/aws-sign/issues" - }, - "dependencies": {}, - "description": "AWS signing. Originally pulled from LearnBoost/knox, maintained as vendor in request, now a standalone module.", - "devDependencies": {}, - "engines": { - "node": "*" - }, - "homepage": "https://github.com/mikeal/aws-sign#readme", - "license": "Apache-2.0", - "main": "index.js", - "name": "aws-sign2", - "optionalDependencies": {}, - "repository": { - "url": "git+https://github.com/mikeal/aws-sign.git" - }, - "version": "0.6.0" -} diff --git a/web/node_modules/aws4/.npmignore b/web/node_modules/aws4/.npmignore deleted file mode 100644 index 6c6ade6..0000000 --- a/web/node_modules/aws4/.npmignore +++ /dev/null @@ -1,4 +0,0 @@ -test -examples -example.js -browser diff --git a/web/node_modules/aws4/.tern-port b/web/node_modules/aws4/.tern-port deleted file mode 100644 index 7fd1b52..0000000 --- a/web/node_modules/aws4/.tern-port +++ /dev/null @@ -1 +0,0 @@ -62638 \ No newline at end of file diff --git a/web/node_modules/aws4/.travis.yml b/web/node_modules/aws4/.travis.yml deleted file mode 100644 index 61d0634..0000000 --- a/web/node_modules/aws4/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" - - "0.12" - - "4.2" diff --git a/web/node_modules/aws4/LICENSE b/web/node_modules/aws4/LICENSE deleted file mode 100644 index 4f321e5..0000000 --- a/web/node_modules/aws4/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright 2013 Michael Hart (michael.hart.au@gmail.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/web/node_modules/aws4/README.md b/web/node_modules/aws4/README.md deleted file mode 100644 index 6b002d0..0000000 --- a/web/node_modules/aws4/README.md +++ /dev/null @@ -1,523 +0,0 @@ -aws4 ----- - -[![Build Status](https://secure.travis-ci.org/mhart/aws4.png?branch=master)](http://travis-ci.org/mhart/aws4) - -A small utility to sign vanilla node.js http(s) request options using Amazon's -[AWS Signature Version 4](http://docs.amazonwebservices.com/general/latest/gr/signature-version-4.html). - -Can also be used [in the browser](./browser). - -This signature is supported by nearly all Amazon services, including -[S3](http://docs.aws.amazon.com/AmazonS3/latest/API/), -[EC2](http://docs.aws.amazon.com/AWSEC2/latest/APIReference/), -[DynamoDB](http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/API.html), -[Kinesis](http://docs.aws.amazon.com/kinesis/latest/APIReference/), -[Lambda](http://docs.aws.amazon.com/lambda/latest/dg/API_Reference.html), -[SQS](http://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/), -[SNS](http://docs.aws.amazon.com/sns/latest/api/), -[IAM](http://docs.aws.amazon.com/IAM/latest/APIReference/), -[STS](http://docs.aws.amazon.com/STS/latest/APIReference/), -[RDS](http://docs.aws.amazon.com/AmazonRDS/latest/APIReference/), -[CloudWatch](http://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/), -[CloudWatch Logs](http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/), -[CodeDeploy](http://docs.aws.amazon.com/codedeploy/latest/APIReference/), -[CloudFront](http://docs.aws.amazon.com/AmazonCloudFront/latest/APIReference/), -[CloudTrail](http://docs.aws.amazon.com/awscloudtrail/latest/APIReference/), -[ElastiCache](http://docs.aws.amazon.com/AmazonElastiCache/latest/APIReference/), -[EMR](http://docs.aws.amazon.com/ElasticMapReduce/latest/API/), -[Glacier](http://docs.aws.amazon.com/amazonglacier/latest/dev/amazon-glacier-api.html), -[CloudSearch](http://docs.aws.amazon.com/cloudsearch/latest/developerguide/APIReq.html), -[Elastic Load Balancing](http://docs.aws.amazon.com/ElasticLoadBalancing/latest/APIReference/), -[Elastic Transcoder](http://docs.aws.amazon.com/elastictranscoder/latest/developerguide/api-reference.html), -[CloudFormation](http://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/), -[Elastic Beanstalk](http://docs.aws.amazon.com/elasticbeanstalk/latest/api/), -[Storage Gateway](http://docs.aws.amazon.com/storagegateway/latest/userguide/AWSStorageGatewayAPI.html), -[Data Pipeline](http://docs.aws.amazon.com/datapipeline/latest/APIReference/), -[Direct Connect](http://docs.aws.amazon.com/directconnect/latest/APIReference/), -[Redshift](http://docs.aws.amazon.com/redshift/latest/APIReference/), -[OpsWorks](http://docs.aws.amazon.com/opsworks/latest/APIReference/), -[SES](http://docs.aws.amazon.com/ses/latest/APIReference/), -[SWF](http://docs.aws.amazon.com/amazonswf/latest/apireference/), -[AutoScaling](http://docs.aws.amazon.com/AutoScaling/latest/APIReference/), -[Mobile Analytics](http://docs.aws.amazon.com/mobileanalytics/latest/ug/server-reference.html), -[Cognito Identity](http://docs.aws.amazon.com/cognitoidentity/latest/APIReference/), -[Cognito Sync](http://docs.aws.amazon.com/cognitosync/latest/APIReference/), -[Container Service](http://docs.aws.amazon.com/AmazonECS/latest/APIReference/), -[AppStream](http://docs.aws.amazon.com/appstream/latest/developerguide/appstream-api-rest.html), -[Key Management Service](http://docs.aws.amazon.com/kms/latest/APIReference/), -[Config](http://docs.aws.amazon.com/config/latest/APIReference/), -[CloudHSM](http://docs.aws.amazon.com/cloudhsm/latest/dg/api-ref.html), -[Route53](http://docs.aws.amazon.com/Route53/latest/APIReference/requests-rest.html) and -[Route53 Domains](http://docs.aws.amazon.com/Route53/latest/APIReference/requests-rpc.html). - -Indeed, the only AWS services that *don't* support v4 as of 2014-12-30 are -[Import/Export](http://docs.aws.amazon.com/AWSImportExport/latest/DG/api-reference.html) and -[SimpleDB](http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/SDB_API.html) -(they only support [AWS Signature Version 2](https://github.com/mhart/aws2)). - -It also provides defaults for a number of core AWS headers and -request parameters, making it very easy to query AWS services, or -build out a fully-featured AWS library. - -Example -------- - -```javascript -var http = require('http'), - https = require('https'), - aws4 = require('aws4') - -// given an options object you could pass to http.request -var opts = {host: 'sqs.us-east-1.amazonaws.com', path: '/?Action=ListQueues'} - -// alternatively (as aws4 can infer the host): -opts = {service: 'sqs', region: 'us-east-1', path: '/?Action=ListQueues'} - -// alternatively (as us-east-1 is default): -opts = {service: 'sqs', path: '/?Action=ListQueues'} - -aws4.sign(opts) // assumes AWS credentials are available in process.env - -console.log(opts) -/* -{ - host: 'sqs.us-east-1.amazonaws.com', - path: '/?Action=ListQueues', - headers: { - Host: 'sqs.us-east-1.amazonaws.com', - 'X-Amz-Date': '20121226T061030Z', - Authorization: 'AWS4-HMAC-SHA256 Credential=ABCDEF/20121226/us-east-1/sqs/aws4_request, ...' - } -} -*/ - -// we can now use this to query AWS using the standard node.js http API -http.request(opts, function(res) { res.pipe(process.stdout) }).end() -/* - - -... -*/ -``` - -More options ------------- - -```javascript -// you can also pass AWS credentials in explicitly (otherwise taken from process.env) -aws4.sign(opts, {accessKeyId: '', secretAccessKey: ''}) - -// can also add the signature to query strings -aws4.sign({service: 's3', path: '/my-bucket?X-Amz-Expires=12345', signQuery: true}) - -// create a utility function to pipe to stdout (with https this time) -function request(o) { https.request(o, function(res) { res.pipe(process.stdout) }).end(o.body || '') } - -// aws4 can infer the HTTP method if a body is passed in -// method will be POST and Content-Type: 'application/x-www-form-urlencoded; charset=utf-8' -request(aws4.sign({service: 'iam', body: 'Action=ListGroups&Version=2010-05-08'})) -/* - -... -*/ - -// can specify any custom option or header as per usual -request(aws4.sign({ - service: 'dynamodb', - region: 'ap-southeast-2', - method: 'POST', - path: '/', - headers: { - 'Content-Type': 'application/x-amz-json-1.0', - 'X-Amz-Target': 'DynamoDB_20120810.ListTables' - }, - body: '{}' -})) -/* -{"TableNames":[]} -... -*/ - -// works with all other services that support Signature Version 4 - -request(aws4.sign({service: 's3', path: '/', signQuery: true})) -/* - -... -*/ - -request(aws4.sign({service: 'ec2', path: '/?Action=DescribeRegions&Version=2014-06-15'})) -/* - -... -*/ - -request(aws4.sign({service: 'sns', path: '/?Action=ListTopics&Version=2010-03-31'})) -/* - -... -*/ - -request(aws4.sign({service: 'sts', path: '/?Action=GetSessionToken&Version=2011-06-15'})) -/* - -... -*/ - -request(aws4.sign({service: 'cloudsearch', path: '/?Action=ListDomainNames&Version=2013-01-01'})) -/* - -... -*/ - -request(aws4.sign({service: 'ses', path: '/?Action=ListIdentities&Version=2010-12-01'})) -/* - -... -*/ - -request(aws4.sign({service: 'autoscaling', path: '/?Action=DescribeAutoScalingInstances&Version=2011-01-01'})) -/* - -... -*/ - -request(aws4.sign({service: 'elasticloadbalancing', path: '/?Action=DescribeLoadBalancers&Version=2012-06-01'})) -/* - -... -*/ - -request(aws4.sign({service: 'cloudformation', path: '/?Action=ListStacks&Version=2010-05-15'})) -/* - -... -*/ - -request(aws4.sign({service: 'elasticbeanstalk', path: '/?Action=ListAvailableSolutionStacks&Version=2010-12-01'})) -/* - -... -*/ - -request(aws4.sign({service: 'rds', path: '/?Action=DescribeDBInstances&Version=2012-09-17'})) -/* - -... -*/ - -request(aws4.sign({service: 'monitoring', path: '/?Action=ListMetrics&Version=2010-08-01'})) -/* - -... -*/ - -request(aws4.sign({service: 'redshift', path: '/?Action=DescribeClusters&Version=2012-12-01'})) -/* - -... -*/ - -request(aws4.sign({service: 'cloudfront', path: '/2014-05-31/distribution'})) -/* - -... -*/ - -request(aws4.sign({service: 'elasticache', path: '/?Action=DescribeCacheClusters&Version=2014-07-15'})) -/* - -... -*/ - -request(aws4.sign({service: 'elasticmapreduce', path: '/?Action=DescribeJobFlows&Version=2009-03-31'})) -/* - -... -*/ - -request(aws4.sign({service: 'route53', path: '/2013-04-01/hostedzone'})) -/* - -... -*/ - -request(aws4.sign({service: 'appstream', path: '/applications'})) -/* -{"_links":{"curie":[{"href":"http://docs.aws.amazon.com/appstream/latest/... -... -*/ - -request(aws4.sign({service: 'cognito-sync', path: '/identitypools'})) -/* -{"Count":0,"IdentityPoolUsages":[],"MaxResults":16,"NextToken":null} -... -*/ - -request(aws4.sign({service: 'elastictranscoder', path: '/2012-09-25/pipelines'})) -/* -{"NextPageToken":null,"Pipelines":[]} -... -*/ - -request(aws4.sign({service: 'lambda', path: '/2014-11-13/functions/'})) -/* -{"Functions":[],"NextMarker":null} -... -*/ - -request(aws4.sign({service: 'ecs', path: '/?Action=ListClusters&Version=2014-11-13'})) -/* - -... -*/ - -request(aws4.sign({service: 'glacier', path: '/-/vaults', headers: {'X-Amz-Glacier-Version': '2012-06-01'}})) -/* -{"Marker":null,"VaultList":[]} -... -*/ - -request(aws4.sign({service: 'storagegateway', body: '{}', headers: { - 'Content-Type': 'application/x-amz-json-1.1', - 'X-Amz-Target': 'StorageGateway_20120630.ListGateways' -}})) -/* -{"Gateways":[]} -... -*/ - -request(aws4.sign({service: 'datapipeline', body: '{}', headers: { - 'Content-Type': 'application/x-amz-json-1.1', - 'X-Amz-Target': 'DataPipeline.ListPipelines' -}})) -/* -{"hasMoreResults":false,"pipelineIdList":[]} -... -*/ - -request(aws4.sign({service: 'opsworks', body: '{}', headers: { - 'Content-Type': 'application/x-amz-json-1.1', - 'X-Amz-Target': 'OpsWorks_20130218.DescribeStacks' -}})) -/* -{"Stacks":[]} -... -*/ - -request(aws4.sign({service: 'route53domains', body: '{}', headers: { - 'Content-Type': 'application/x-amz-json-1.1', - 'X-Amz-Target': 'Route53Domains_v20140515.ListDomains' -}})) -/* -{"Domains":[]} -... -*/ - -request(aws4.sign({service: 'kinesis', body: '{}', headers: { - 'Content-Type': 'application/x-amz-json-1.1', - 'X-Amz-Target': 'Kinesis_20131202.ListStreams' -}})) -/* -{"HasMoreStreams":false,"StreamNames":[]} -... -*/ - -request(aws4.sign({service: 'cloudtrail', body: '{}', headers: { - 'Content-Type': 'application/x-amz-json-1.1', - 'X-Amz-Target': 'CloudTrail_20131101.DescribeTrails' -}})) -/* -{"trailList":[]} -... -*/ - -request(aws4.sign({service: 'logs', body: '{}', headers: { - 'Content-Type': 'application/x-amz-json-1.1', - 'X-Amz-Target': 'Logs_20140328.DescribeLogGroups' -}})) -/* -{"logGroups":[]} -... -*/ - -request(aws4.sign({service: 'codedeploy', body: '{}', headers: { - 'Content-Type': 'application/x-amz-json-1.1', - 'X-Amz-Target': 'CodeDeploy_20141006.ListApplications' -}})) -/* -{"applications":[]} -... -*/ - -request(aws4.sign({service: 'directconnect', body: '{}', headers: { - 'Content-Type': 'application/x-amz-json-1.1', - 'X-Amz-Target': 'OvertureService.DescribeConnections' -}})) -/* -{"connections":[]} -... -*/ - -request(aws4.sign({service: 'kms', body: '{}', headers: { - 'Content-Type': 'application/x-amz-json-1.1', - 'X-Amz-Target': 'TrentService.ListKeys' -}})) -/* -{"Keys":[],"Truncated":false} -... -*/ - -request(aws4.sign({service: 'config', body: '{}', headers: { - 'Content-Type': 'application/x-amz-json-1.1', - 'X-Amz-Target': 'StarlingDoveService.DescribeDeliveryChannels' -}})) -/* -{"DeliveryChannels":[]} -... -*/ - -request(aws4.sign({service: 'cloudhsm', body: '{}', headers: { - 'Content-Type': 'application/x-amz-json-1.1', - 'X-Amz-Target': 'CloudHsmFrontendService.ListAvailableZones' -}})) -/* -{"AZList":["us-east-1a","us-east-1b","us-east-1c"]} -... -*/ - -request(aws4.sign({ - service: 'swf', - body: '{"registrationStatus":"REGISTERED"}', - headers: { - 'Content-Type': 'application/x-amz-json-1.0', - 'X-Amz-Target': 'SimpleWorkflowService.ListDomains' - } -})) -/* -{"domainInfos":[]} -... -*/ - -request(aws4.sign({ - service: 'cognito-identity', - body: '{"MaxResults": 1}', - headers: { - 'Content-Type': 'application/x-amz-json-1.1', - 'X-Amz-Target': 'AWSCognitoIdentityService.ListIdentityPools' - } -})) -/* -{"IdentityPools":[]} -... -*/ - -request(aws4.sign({ - service: 'mobileanalytics', - path: '/2014-06-05/events', - body: JSON.stringify({events:[{ - eventType: 'a', - timestamp: new Date().toISOString(), - session: {}, - }]}), - headers: { - 'Content-Type': 'application/json', - 'X-Amz-Client-Context': JSON.stringify({ - client: {client_id: 'a', app_title: 'a'}, - custom: {}, - env: {platform: 'a'}, - services: {}, - }), - } -})) -/* -(HTTP 202, empty response) -*/ - -// Generate CodeCommit Git access password -var signer = new aws4.RequestSigner({ - service: 'codecommit', - host: 'git-codecommit.us-east-1.amazonaws.com', - method: 'GIT', - path: '/v1/repos/MyAwesomeRepo', -}) -var password = signer.getDateTime() + 'Z' + signer.signature() -``` - -API ---- - -### aws4.sign(requestOptions, [credentials]) - -This calculates and populates the `Authorization` header of -`requestOptions`, and any other necessary AWS headers and/or request -options. Returns `requestOptions` as a convenience for chaining. - -`requestOptions` is an object holding the same options that the node.js -[http.request](http://nodejs.org/docs/latest/api/http.html#http_http_request_options_callback) -function takes. - -The following properties of `requestOptions` are used in the signing or -populated if they don't already exist: - -- `hostname` or `host` (will be determined from `service` and `region` if not given) -- `method` (will use `'GET'` if not given or `'POST'` if there is a `body`) -- `path` (will use `'/'` if not given) -- `body` (will use `''` if not given) -- `service` (will be calculated from `hostname` or `host` if not given) -- `region` (will be calculated from `hostname` or `host` or use `'us-east-1'` if not given) -- `headers['Host']` (will use `hostname` or `host` or be calculated if not given) -- `headers['Content-Type']` (will use `'application/x-www-form-urlencoded; charset=utf-8'` - if not given and there is a `body`) -- `headers['Date']` (used to calculate the signature date if given, otherwise `new Date` is used) - -Your AWS credentials (which can be found in your -[AWS console](https://portal.aws.amazon.com/gp/aws/securityCredentials)) -can be specified in one of two ways: - -- As the second argument, like this: - -```javascript -aws4.sign(requestOptions, { - secretAccessKey: "", - accessKeyId: "", - sessionToken: "" -}) -``` - -- From `process.env`, such as this: - -``` -export AWS_SECRET_ACCESS_KEY="" -export AWS_ACCESS_KEY_ID="" -export AWS_SESSION_TOKEN="" -``` - -(will also use `AWS_ACCESS_KEY` and `AWS_SECRET_KEY` if available) - -The `sessionToken` property and `AWS_SESSION_TOKEN` environment variable are optional for signing -with [IAM STS temporary credentials](http://docs.aws.amazon.com/STS/latest/UsingSTS/using-temp-creds.html). - -Installation ------------- - -With [npm](http://npmjs.org/) do: - -``` -npm install aws4 -``` - -Can also be used [in the browser](./browser). - -Thanks ------- - -Thanks to [@jed](https://github.com/jed) for his -[dynamo-client](https://github.com/jed/dynamo-client) lib where I first -committed and subsequently extracted this code. - -Also thanks to the -[official node.js AWS SDK](https://github.com/aws/aws-sdk-js) for giving -me a start on implementing the v4 signature. - diff --git a/web/node_modules/aws4/aws4.js b/web/node_modules/aws4/aws4.js deleted file mode 100644 index 0cff0f0..0000000 --- a/web/node_modules/aws4/aws4.js +++ /dev/null @@ -1,332 +0,0 @@ -var aws4 = exports, - url = require('url'), - querystring = require('querystring'), - crypto = require('crypto'), - lru = require('./lru'), - credentialsCache = lru(1000) - -// http://docs.amazonwebservices.com/general/latest/gr/signature-version-4.html - -function hmac(key, string, encoding) { - return crypto.createHmac('sha256', key).update(string, 'utf8').digest(encoding) -} - -function hash(string, encoding) { - return crypto.createHash('sha256').update(string, 'utf8').digest(encoding) -} - -// This function assumes the string has already been percent encoded -function encodeRfc3986(urlEncodedString) { - return urlEncodedString.replace(/[!'()*]/g, function(c) { - return '%' + c.charCodeAt(0).toString(16).toUpperCase() - }) -} - -// request: { path | body, [host], [method], [headers], [service], [region] } -// credentials: { accessKeyId, secretAccessKey, [sessionToken] } -function RequestSigner(request, credentials) { - - if (typeof request === 'string') request = url.parse(request) - - var headers = request.headers = (request.headers || {}), - hostParts = this.matchHost(request.hostname || request.host || headers.Host || headers.host) - - this.request = request - this.credentials = credentials || this.defaultCredentials() - - this.service = request.service || hostParts[0] || '' - this.region = request.region || hostParts[1] || 'us-east-1' - - // SES uses a different domain from the service name - if (this.service === 'email') this.service = 'ses' - - if (!request.method && request.body) - request.method = 'POST' - - if (!headers.Host && !headers.host) { - headers.Host = request.hostname || request.host || this.createHost() - - // If a port is specified explicitly, use it as is - if (request.port) - headers.Host += ':' + request.port - } - if (!request.hostname && !request.host) - request.hostname = headers.Host || headers.host - - this.isCodeCommitGit = this.service === 'codecommit' && request.method === 'GIT' -} - -RequestSigner.prototype.matchHost = function(host) { - var match = (host || '').match(/([^\.]+)\.(?:([^\.]*)\.)?amazonaws\.com$/) - var hostParts = (match || []).slice(1, 3) - - // ES's hostParts are sometimes the other way round, if the value that is expected - // to be region equals ‘es’ switch them back - // e.g. search-cluster-name-aaaa00aaaa0aaa0aaaaaaa0aaa.us-east-1.es.amazonaws.com - if (hostParts[1] === 'es') - hostParts = hostParts.reverse() - - return hostParts -} - -// http://docs.aws.amazon.com/general/latest/gr/rande.html -RequestSigner.prototype.isSingleRegion = function() { - // Special case for S3 and SimpleDB in us-east-1 - if (['s3', 'sdb'].indexOf(this.service) >= 0 && this.region === 'us-east-1') return true - - return ['cloudfront', 'ls', 'route53', 'iam', 'importexport', 'sts'] - .indexOf(this.service) >= 0 -} - -RequestSigner.prototype.createHost = function() { - var region = this.isSingleRegion() ? '' : - (this.service === 's3' && this.region !== 'us-east-1' ? '-' : '.') + this.region, - service = this.service === 'ses' ? 'email' : this.service - return service + region + '.amazonaws.com' -} - -RequestSigner.prototype.prepareRequest = function() { - this.parsePath() - - var request = this.request, headers = request.headers, query - - if (request.signQuery) { - - this.parsedPath.query = query = this.parsedPath.query || {} - - if (this.credentials.sessionToken) - query['X-Amz-Security-Token'] = this.credentials.sessionToken - - if (this.service === 's3' && !query['X-Amz-Expires']) - query['X-Amz-Expires'] = 86400 - - if (query['X-Amz-Date']) - this.datetime = query['X-Amz-Date'] - else - query['X-Amz-Date'] = this.getDateTime() - - query['X-Amz-Algorithm'] = 'AWS4-HMAC-SHA256' - query['X-Amz-Credential'] = this.credentials.accessKeyId + '/' + this.credentialString() - query['X-Amz-SignedHeaders'] = this.signedHeaders() - - } else { - - if (!request.doNotModifyHeaders && !this.isCodeCommitGit) { - if (request.body && !headers['Content-Type'] && !headers['content-type']) - headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8' - - if (request.body && !headers['Content-Length'] && !headers['content-length']) - headers['Content-Length'] = Buffer.byteLength(request.body) - - if (this.credentials.sessionToken && !headers['X-Amz-Security-Token'] && !headers['x-amz-security-token']) - headers['X-Amz-Security-Token'] = this.credentials.sessionToken - - if (this.service === 's3' && !headers['X-Amz-Content-Sha256'] && !headers['x-amz-content-sha256']) - headers['X-Amz-Content-Sha256'] = hash(this.request.body || '', 'hex') - - if (headers['X-Amz-Date'] || headers['x-amz-date']) - this.datetime = headers['X-Amz-Date'] || headers['x-amz-date'] - else - headers['X-Amz-Date'] = this.getDateTime() - } - - delete headers.Authorization - delete headers.authorization - } -} - -RequestSigner.prototype.sign = function() { - if (!this.parsedPath) this.prepareRequest() - - if (this.request.signQuery) { - this.parsedPath.query['X-Amz-Signature'] = this.signature() - } else { - this.request.headers.Authorization = this.authHeader() - } - - this.request.path = this.formatPath() - - return this.request -} - -RequestSigner.prototype.getDateTime = function() { - if (!this.datetime) { - var headers = this.request.headers, - date = new Date(headers.Date || headers.date || new Date) - - this.datetime = date.toISOString().replace(/[:\-]|\.\d{3}/g, '') - - // Remove the trailing 'Z' on the timestamp string for CodeCommit git access - if (this.isCodeCommitGit) this.datetime = this.datetime.slice(0, -1) - } - return this.datetime -} - -RequestSigner.prototype.getDate = function() { - return this.getDateTime().substr(0, 8) -} - -RequestSigner.prototype.authHeader = function() { - return [ - 'AWS4-HMAC-SHA256 Credential=' + this.credentials.accessKeyId + '/' + this.credentialString(), - 'SignedHeaders=' + this.signedHeaders(), - 'Signature=' + this.signature(), - ].join(', ') -} - -RequestSigner.prototype.signature = function() { - var date = this.getDate(), - cacheKey = [this.credentials.secretAccessKey, date, this.region, this.service].join(), - kDate, kRegion, kService, kCredentials = credentialsCache.get(cacheKey) - if (!kCredentials) { - kDate = hmac('AWS4' + this.credentials.secretAccessKey, date) - kRegion = hmac(kDate, this.region) - kService = hmac(kRegion, this.service) - kCredentials = hmac(kService, 'aws4_request') - credentialsCache.set(cacheKey, kCredentials) - } - return hmac(kCredentials, this.stringToSign(), 'hex') -} - -RequestSigner.prototype.stringToSign = function() { - return [ - 'AWS4-HMAC-SHA256', - this.getDateTime(), - this.credentialString(), - hash(this.canonicalString(), 'hex'), - ].join('\n') -} - -RequestSigner.prototype.canonicalString = function() { - if (!this.parsedPath) this.prepareRequest() - - var pathStr = this.parsedPath.path, - query = this.parsedPath.query, - headers = this.request.headers, - queryStr = '', - normalizePath = this.service !== 's3', - decodePath = this.service === 's3' || this.request.doNotEncodePath, - decodeSlashesInPath = this.service === 's3', - firstValOnly = this.service === 's3', - bodyHash - - if (this.service === 's3' && this.request.signQuery) { - bodyHash = 'UNSIGNED-PAYLOAD' - } else if (this.isCodeCommitGit) { - bodyHash = '' - } else { - bodyHash = headers['X-Amz-Content-Sha256'] || headers['x-amz-content-sha256'] || - hash(this.request.body || '', 'hex') - } - - if (query) { - queryStr = encodeRfc3986(querystring.stringify(Object.keys(query).sort().reduce(function(obj, key) { - if (!key) return obj - obj[key] = !Array.isArray(query[key]) ? query[key] : - (firstValOnly ? query[key][0] : query[key].slice().sort()) - return obj - }, {}))) - } - if (pathStr !== '/') { - if (normalizePath) pathStr = pathStr.replace(/\/{2,}/g, '/') - pathStr = pathStr.split('/').reduce(function(path, piece) { - if (normalizePath && piece === '..') { - path.pop() - } else if (!normalizePath || piece !== '.') { - if (decodePath) piece = querystring.unescape(piece) - path.push(encodeRfc3986(querystring.escape(piece))) - } - return path - }, []).join('/') - if (pathStr[0] !== '/') pathStr = '/' + pathStr - if (decodeSlashesInPath) pathStr = pathStr.replace(/%2F/g, '/') - } - - return [ - this.request.method || 'GET', - pathStr, - queryStr, - this.canonicalHeaders() + '\n', - this.signedHeaders(), - bodyHash, - ].join('\n') -} - -RequestSigner.prototype.canonicalHeaders = function() { - var headers = this.request.headers - function trimAll(header) { - return header.toString().trim().replace(/\s+/g, ' ') - } - return Object.keys(headers) - .sort(function(a, b) { return a.toLowerCase() < b.toLowerCase() ? -1 : 1 }) - .map(function(key) { return key.toLowerCase() + ':' + trimAll(headers[key]) }) - .join('\n') -} - -RequestSigner.prototype.signedHeaders = function() { - return Object.keys(this.request.headers) - .map(function(key) { return key.toLowerCase() }) - .sort() - .join(';') -} - -RequestSigner.prototype.credentialString = function() { - return [ - this.getDate(), - this.region, - this.service, - 'aws4_request', - ].join('/') -} - -RequestSigner.prototype.defaultCredentials = function() { - var env = process.env - return { - accessKeyId: env.AWS_ACCESS_KEY_ID || env.AWS_ACCESS_KEY, - secretAccessKey: env.AWS_SECRET_ACCESS_KEY || env.AWS_SECRET_KEY, - sessionToken: env.AWS_SESSION_TOKEN, - } -} - -RequestSigner.prototype.parsePath = function() { - var path = this.request.path || '/', - queryIx = path.indexOf('?'), - query = null - - if (queryIx >= 0) { - query = querystring.parse(path.slice(queryIx + 1)) - path = path.slice(0, queryIx) - } - - // S3 doesn't always encode characters > 127 correctly and - // all services don't encode characters > 255 correctly - // So if there are non-reserved chars (and it's not already all % encoded), just encode them all - if (/[^0-9A-Za-z!'()*\-._~%/]/.test(path)) { - path = path.split('/').map(function(piece) { - return querystring.escape(querystring.unescape(piece)) - }).join('/') - } - - this.parsedPath = { - path: path, - query: query, - } -} - -RequestSigner.prototype.formatPath = function() { - var path = this.parsedPath.path, - query = this.parsedPath.query - - if (!query) return path - - // Services don't support empty query string keys - if (query[''] != null) delete query[''] - - return path + '?' + encodeRfc3986(querystring.stringify(query)) -} - -aws4.RequestSigner = RequestSigner - -aws4.sign = function(request, credentials) { - return new RequestSigner(request, credentials).sign() -} diff --git a/web/node_modules/aws4/lru.js b/web/node_modules/aws4/lru.js deleted file mode 100644 index 333f66a..0000000 --- a/web/node_modules/aws4/lru.js +++ /dev/null @@ -1,96 +0,0 @@ -module.exports = function(size) { - return new LruCache(size) -} - -function LruCache(size) { - this.capacity = size | 0 - this.map = Object.create(null) - this.list = new DoublyLinkedList() -} - -LruCache.prototype.get = function(key) { - var node = this.map[key] - if (node == null) return undefined - this.used(node) - return node.val -} - -LruCache.prototype.set = function(key, val) { - var node = this.map[key] - if (node != null) { - node.val = val - } else { - if (!this.capacity) this.prune() - if (!this.capacity) return false - node = new DoublyLinkedNode(key, val) - this.map[key] = node - this.capacity-- - } - this.used(node) - return true -} - -LruCache.prototype.used = function(node) { - this.list.moveToFront(node) -} - -LruCache.prototype.prune = function() { - var node = this.list.pop() - if (node != null) { - delete this.map[node.key] - this.capacity++ - } -} - - -function DoublyLinkedList() { - this.firstNode = null - this.lastNode = null -} - -DoublyLinkedList.prototype.moveToFront = function(node) { - if (this.firstNode == node) return - - this.remove(node) - - if (this.firstNode == null) { - this.firstNode = node - this.lastNode = node - node.prev = null - node.next = null - } else { - node.prev = null - node.next = this.firstNode - node.next.prev = node - this.firstNode = node - } -} - -DoublyLinkedList.prototype.pop = function() { - var lastNode = this.lastNode - if (lastNode != null) { - this.remove(lastNode) - } - return lastNode -} - -DoublyLinkedList.prototype.remove = function(node) { - if (this.firstNode == node) { - this.firstNode = node.next - } else if (node.prev != null) { - node.prev.next = node.next - } - if (this.lastNode == node) { - this.lastNode = node.prev - } else if (node.next != null) { - node.next.prev = node.prev - } -} - - -function DoublyLinkedNode(key, val) { - this.key = key - this.val = val - this.prev = null - this.next = null -} diff --git a/web/node_modules/aws4/package.json b/web/node_modules/aws4/package.json deleted file mode 100644 index 27a245f..0000000 --- a/web/node_modules/aws4/package.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "_args": [ - [ - "aws4@1.6.0", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "aws4@1.6.0", - "_id": "aws4@1.6.0", - "_inBundle": false, - "_integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", - "_location": "/aws4", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "aws4@1.6.0", - "name": "aws4", - "escapedName": "aws4", - "rawSpec": "1.6.0", - "saveSpec": null, - "fetchSpec": "1.6.0" - }, - "_requiredBy": [ - "/request" - ], - "_resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "_spec": "1.6.0", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "Michael Hart", - "email": "michael.hart.au@gmail.com", - "url": "http://github.com/mhart" - }, - "bugs": { - "url": "https://github.com/mhart/aws4/issues" - }, - "description": "Signs and prepares requests using AWS Signature Version 4", - "devDependencies": { - "mocha": "^2.4.5", - "should": "^8.2.2" - }, - "homepage": "https://github.com/mhart/aws4#readme", - "keywords": [ - "amazon", - "aws", - "signature", - "s3", - "ec2", - "autoscaling", - "cloudformation", - "elasticloadbalancing", - "elb", - "elasticbeanstalk", - "cloudsearch", - "dynamodb", - "kinesis", - "lambda", - "glacier", - "sqs", - "sns", - "iam", - "sts", - "ses", - "swf", - "storagegateway", - "datapipeline", - "directconnect", - "redshift", - "opsworks", - "rds", - "monitoring", - "cloudtrail", - "cloudfront", - "codedeploy", - "elasticache", - "elasticmapreduce", - "elastictranscoder", - "emr", - "cloudwatch", - "mobileanalytics", - "cognitoidentity", - "cognitosync", - "cognito", - "containerservice", - "ecs", - "appstream", - "keymanagementservice", - "kms", - "config", - "cloudhsm", - "route53", - "route53domains", - "logs" - ], - "license": "MIT", - "main": "aws4.js", - "name": "aws4", - "repository": { - "type": "git", - "url": "git+https://github.com/mhart/aws4.git" - }, - "scripts": { - "test": "mocha ./test/fast.js ./test/slow.js -b -t 100s -R list" - }, - "version": "1.6.0" -} diff --git a/web/node_modules/backo2/.npmignore b/web/node_modules/backo2/.npmignore deleted file mode 100644 index c2658d7..0000000 --- a/web/node_modules/backo2/.npmignore +++ /dev/null @@ -1 +0,0 @@ -node_modules/ diff --git a/web/node_modules/backo2/History.md b/web/node_modules/backo2/History.md deleted file mode 100644 index 8eb28b8..0000000 --- a/web/node_modules/backo2/History.md +++ /dev/null @@ -1,12 +0,0 @@ - -1.0.1 / 2014-02-17 -================== - - * go away decimal point - * history - -1.0.0 / 2014-02-17 -================== - - * add jitter option - * Initial commit diff --git a/web/node_modules/backo2/Makefile b/web/node_modules/backo2/Makefile deleted file mode 100644 index 9987df8..0000000 --- a/web/node_modules/backo2/Makefile +++ /dev/null @@ -1,8 +0,0 @@ - -test: - @./node_modules/.bin/mocha \ - --require should \ - --reporter dot \ - --bail - -.PHONY: test \ No newline at end of file diff --git a/web/node_modules/backo2/Readme.md b/web/node_modules/backo2/Readme.md deleted file mode 100644 index 0df2a39..0000000 --- a/web/node_modules/backo2/Readme.md +++ /dev/null @@ -1,34 +0,0 @@ -# backo - - Simple exponential backoff because the others seem to have weird abstractions. - -## Installation - -``` -$ npm install backo -``` - -## Options - - - `min` initial timeout in milliseconds [100] - - `max` max timeout [10000] - - `jitter` [0] - - `factor` [2] - -## Example - -```js -var Backoff = require('backo'); -var backoff = new Backoff({ min: 100, max: 20000 }); - -setTimeout(function(){ - something.reconnect(); -}, backoff.duration()); - -// later when something works -backoff.reset() -``` - -# License - - MIT diff --git a/web/node_modules/backo2/component.json b/web/node_modules/backo2/component.json deleted file mode 100644 index 994845a..0000000 --- a/web/node_modules/backo2/component.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "backo", - "repo": "segmentio/backo", - "dependencies": {}, - "version": "1.0.1", - "description": "simple backoff without the weird abstractions", - "keywords": ["backoff"], - "license": "MIT", - "scripts": ["index.js"], - "main": "index.js" -} diff --git a/web/node_modules/backo2/index.js b/web/node_modules/backo2/index.js deleted file mode 100644 index fac4429..0000000 --- a/web/node_modules/backo2/index.js +++ /dev/null @@ -1,85 +0,0 @@ - -/** - * Expose `Backoff`. - */ - -module.exports = Backoff; - -/** - * Initialize backoff timer with `opts`. - * - * - `min` initial timeout in milliseconds [100] - * - `max` max timeout [10000] - * - `jitter` [0] - * - `factor` [2] - * - * @param {Object} opts - * @api public - */ - -function Backoff(opts) { - opts = opts || {}; - this.ms = opts.min || 100; - this.max = opts.max || 10000; - this.factor = opts.factor || 2; - this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0; - this.attempts = 0; -} - -/** - * Return the backoff duration. - * - * @return {Number} - * @api public - */ - -Backoff.prototype.duration = function(){ - var ms = this.ms * Math.pow(this.factor, this.attempts++); - if (this.jitter) { - var rand = Math.random(); - var deviation = Math.floor(rand * this.jitter * ms); - ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation; - } - return Math.min(ms, this.max) | 0; -}; - -/** - * Reset the number of attempts. - * - * @api public - */ - -Backoff.prototype.reset = function(){ - this.attempts = 0; -}; - -/** - * Set the minimum duration - * - * @api public - */ - -Backoff.prototype.setMin = function(min){ - this.ms = min; -}; - -/** - * Set the maximum duration - * - * @api public - */ - -Backoff.prototype.setMax = function(max){ - this.max = max; -}; - -/** - * Set the jitter - * - * @api public - */ - -Backoff.prototype.setJitter = function(jitter){ - this.jitter = jitter; -}; - diff --git a/web/node_modules/backo2/package.json b/web/node_modules/backo2/package.json deleted file mode 100644 index 1c76eda..0000000 --- a/web/node_modules/backo2/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "_args": [ - [ - "backo2@1.0.2", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "backo2@1.0.2", - "_id": "backo2@1.0.2", - "_inBundle": false, - "_integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", - "_location": "/backo2", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "backo2@1.0.2", - "name": "backo2", - "escapedName": "backo2", - "rawSpec": "1.0.2", - "saveSpec": null, - "fetchSpec": "1.0.2" - }, - "_requiredBy": [ - "/socket.io-client" - ], - "_resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "_spec": "1.0.2", - "_where": "/home/treharne/Documents/web/cdt-py", - "bugs": { - "url": "https://github.com/mokesmokes/backo/issues" - }, - "dependencies": {}, - "description": "simple backoff based on segmentio/backo", - "devDependencies": { - "mocha": "*", - "should": "*" - }, - "homepage": "https://github.com/mokesmokes/backo#readme", - "keywords": [ - "backoff" - ], - "license": "MIT", - "name": "backo2", - "repository": { - "type": "git", - "url": "git+https://github.com/mokesmokes/backo.git" - }, - "version": "1.0.2" -} diff --git a/web/node_modules/backo2/test/index.js b/web/node_modules/backo2/test/index.js deleted file mode 100644 index ea1f6de..0000000 --- a/web/node_modules/backo2/test/index.js +++ /dev/null @@ -1,18 +0,0 @@ - -var Backoff = require('..'); -var assert = require('assert'); - -describe('.duration()', function(){ - it('should increase the backoff', function(){ - var b = new Backoff; - - assert(100 == b.duration()); - assert(200 == b.duration()); - assert(400 == b.duration()); - assert(800 == b.duration()); - - b.reset(); - assert(100 == b.duration()); - assert(200 == b.duration()); - }) -}) \ No newline at end of file diff --git a/web/node_modules/balanced-match/.npmignore b/web/node_modules/balanced-match/.npmignore deleted file mode 100644 index ae5d8c3..0000000 --- a/web/node_modules/balanced-match/.npmignore +++ /dev/null @@ -1,5 +0,0 @@ -test -.gitignore -.travis.yml -Makefile -example.js diff --git a/web/node_modules/balanced-match/LICENSE.md b/web/node_modules/balanced-match/LICENSE.md deleted file mode 100644 index 2cdc8e4..0000000 --- a/web/node_modules/balanced-match/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -(MIT) - -Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/web/node_modules/balanced-match/README.md b/web/node_modules/balanced-match/README.md deleted file mode 100644 index 08e918c..0000000 --- a/web/node_modules/balanced-match/README.md +++ /dev/null @@ -1,91 +0,0 @@ -# balanced-match - -Match balanced string pairs, like `{` and `}` or `` and ``. Supports regular expressions as well! - -[![build status](https://secure.travis-ci.org/juliangruber/balanced-match.svg)](http://travis-ci.org/juliangruber/balanced-match) -[![downloads](https://img.shields.io/npm/dm/balanced-match.svg)](https://www.npmjs.org/package/balanced-match) - -[![testling badge](https://ci.testling.com/juliangruber/balanced-match.png)](https://ci.testling.com/juliangruber/balanced-match) - -## Example - -Get the first matching pair of braces: - -```js -var balanced = require('balanced-match'); - -console.log(balanced('{', '}', 'pre{in{nested}}post')); -console.log(balanced('{', '}', 'pre{first}between{second}post')); -console.log(balanced(/\s+\{\s+/, /\s+\}\s+/, 'pre { in{nest} } post')); -``` - -The matches are: - -```bash -$ node example.js -{ start: 3, end: 14, pre: 'pre', body: 'in{nested}', post: 'post' } -{ start: 3, - end: 9, - pre: 'pre', - body: 'first', - post: 'between{second}post' } -{ start: 3, end: 17, pre: 'pre', body: 'in{nest}', post: 'post' } -``` - -## API - -### var m = balanced(a, b, str) - -For the first non-nested matching pair of `a` and `b` in `str`, return an -object with those keys: - -* **start** the index of the first match of `a` -* **end** the index of the matching `b` -* **pre** the preamble, `a` and `b` not included -* **body** the match, `a` and `b` not included -* **post** the postscript, `a` and `b` not included - -If there's no match, `undefined` will be returned. - -If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `['{', 'a', '']` and `{a}}` will match `['', 'a', '}']`. - -### var r = balanced.range(a, b, str) - -For the first non-nested matching pair of `a` and `b` in `str`, return an -array with indexes: `[ , ]`. - -If there's no match, `undefined` will be returned. - -If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `[ 1, 3 ]` and `{a}}` will match `[0, 2]`. - -## Installation - -With [npm](https://npmjs.org) do: - -```bash -npm install balanced-match -``` - -## License - -(MIT) - -Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/web/node_modules/balanced-match/index.js b/web/node_modules/balanced-match/index.js deleted file mode 100644 index 1685a76..0000000 --- a/web/node_modules/balanced-match/index.js +++ /dev/null @@ -1,59 +0,0 @@ -'use strict'; -module.exports = balanced; -function balanced(a, b, str) { - if (a instanceof RegExp) a = maybeMatch(a, str); - if (b instanceof RegExp) b = maybeMatch(b, str); - - var r = range(a, b, str); - - return r && { - start: r[0], - end: r[1], - pre: str.slice(0, r[0]), - body: str.slice(r[0] + a.length, r[1]), - post: str.slice(r[1] + b.length) - }; -} - -function maybeMatch(reg, str) { - var m = str.match(reg); - return m ? m[0] : null; -} - -balanced.range = range; -function range(a, b, str) { - var begs, beg, left, right, result; - var ai = str.indexOf(a); - var bi = str.indexOf(b, ai + 1); - var i = ai; - - if (ai >= 0 && bi > 0) { - begs = []; - left = str.length; - - while (i >= 0 && !result) { - if (i == ai) { - begs.push(i); - ai = str.indexOf(a, i + 1); - } else if (begs.length == 1) { - result = [ begs.pop(), bi ]; - } else { - beg = begs.pop(); - if (beg < left) { - left = beg; - right = bi; - } - - bi = str.indexOf(b, i + 1); - } - - i = ai < bi && ai >= 0 ? ai : bi; - } - - if (begs.length) { - result = [ left, right ]; - } - } - - return result; -} diff --git a/web/node_modules/balanced-match/package.json b/web/node_modules/balanced-match/package.json deleted file mode 100644 index 9544fa4..0000000 --- a/web/node_modules/balanced-match/package.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "_args": [ - [ - "balanced-match@1.0.0", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "balanced-match@1.0.0", - "_id": "balanced-match@1.0.0", - "_inBundle": false, - "_integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "_location": "/balanced-match", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "balanced-match@1.0.0", - "name": "balanced-match", - "escapedName": "balanced-match", - "rawSpec": "1.0.0", - "saveSpec": null, - "fetchSpec": "1.0.0" - }, - "_requiredBy": [ - "/brace-expansion" - ], - "_resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "_spec": "1.0.0", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "Julian Gruber", - "email": "mail@juliangruber.com", - "url": "http://juliangruber.com" - }, - "bugs": { - "url": "https://github.com/juliangruber/balanced-match/issues" - }, - "dependencies": {}, - "description": "Match balanced character pairs, like \"{\" and \"}\"", - "devDependencies": { - "matcha": "^0.7.0", - "tape": "^4.6.0" - }, - "homepage": "https://github.com/juliangruber/balanced-match", - "keywords": [ - "match", - "regexp", - "test", - "balanced", - "parse" - ], - "license": "MIT", - "main": "index.js", - "name": "balanced-match", - "repository": { - "type": "git", - "url": "git://github.com/juliangruber/balanced-match.git" - }, - "scripts": { - "bench": "make bench", - "test": "make test" - }, - "testling": { - "files": "test/*.js", - "browsers": [ - "ie/8..latest", - "firefox/20..latest", - "firefox/nightly", - "chrome/25..latest", - "chrome/canary", - "opera/12..latest", - "opera/next", - "safari/5.1..latest", - "ipad/6.0..latest", - "iphone/6.0..latest", - "android-browser/4.2..latest" - ] - }, - "version": "1.0.0" -} diff --git a/web/node_modules/base64-arraybuffer/.npmignore b/web/node_modules/base64-arraybuffer/.npmignore deleted file mode 100644 index 332ee5a..0000000 --- a/web/node_modules/base64-arraybuffer/.npmignore +++ /dev/null @@ -1,3 +0,0 @@ -/node_modules/ -Gruntfile.js -/test/ diff --git a/web/node_modules/base64-arraybuffer/.travis.yml b/web/node_modules/base64-arraybuffer/.travis.yml deleted file mode 100644 index 19259a5..0000000 --- a/web/node_modules/base64-arraybuffer/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: node_js -node_js: -- '0.12' -- iojs-1 -- iojs-2 -- iojs-3 -- '4.1' -before_script: -- npm install -before_install: npm install -g npm@'>=2.13.5' -deploy: - provider: npm - email: niklasvh@gmail.com - api_key: - secure: oHV9ArprTj5WOk7MP1UF7QMJ70huXw+y7xXb5wF4+V2H8Hyfa5TfE0DiOmqrube1WXTeH1FLgq54shp/sJWi47Hkg/GyeoB5NnsPhYEaJkaON9UG5blML+ODiNVsEnq/1kNBQ8e0+0JItMPLGySKyFmuZ3yflulXKS8O88mfINo= - on: - tags: true - branch: master - repo: niklasvh/base64-arraybuffer diff --git a/web/node_modules/base64-arraybuffer/LICENSE-MIT b/web/node_modules/base64-arraybuffer/LICENSE-MIT deleted file mode 100644 index ed27b41..0000000 --- a/web/node_modules/base64-arraybuffer/LICENSE-MIT +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2012 Niklas von Hertzen - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. diff --git a/web/node_modules/base64-arraybuffer/README.md b/web/node_modules/base64-arraybuffer/README.md deleted file mode 100644 index 50009e4..0000000 --- a/web/node_modules/base64-arraybuffer/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# base64-arraybuffer - -[![Build Status](https://travis-ci.org/niklasvh/base64-arraybuffer.png)](https://travis-ci.org/niklasvh/base64-arraybuffer) -[![NPM Downloads](https://img.shields.io/npm/dm/base64-arraybuffer.svg)](https://www.npmjs.org/package/base64-arraybuffer) -[![NPM Version](https://img.shields.io/npm/v/base64-arraybuffer.svg)](https://www.npmjs.org/package/base64-arraybuffer) - -Encode/decode base64 data into ArrayBuffers - -## Getting Started -Install the module with: `npm install base64-arraybuffer` - -## API -The library encodes and decodes base64 to and from ArrayBuffers - - - __encode(buffer)__ - Encodes `ArrayBuffer` into base64 string - - __decode(str)__ - Decodes base64 string to `ArrayBuffer` - -## License -Copyright (c) 2012 Niklas von Hertzen -Licensed under the MIT license. diff --git a/web/node_modules/base64-arraybuffer/lib/base64-arraybuffer.js b/web/node_modules/base64-arraybuffer/lib/base64-arraybuffer.js deleted file mode 100644 index e6b6306..0000000 --- a/web/node_modules/base64-arraybuffer/lib/base64-arraybuffer.js +++ /dev/null @@ -1,67 +0,0 @@ -/* - * base64-arraybuffer - * https://github.com/niklasvh/base64-arraybuffer - * - * Copyright (c) 2012 Niklas von Hertzen - * Licensed under the MIT license. - */ -(function(){ - "use strict"; - - var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - // Use a lookup table to find the index. - var lookup = new Uint8Array(256); - for (var i = 0; i < chars.length; i++) { - lookup[chars.charCodeAt(i)] = i; - } - - exports.encode = function(arraybuffer) { - var bytes = new Uint8Array(arraybuffer), - i, len = bytes.length, base64 = ""; - - for (i = 0; i < len; i+=3) { - base64 += chars[bytes[i] >> 2]; - base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; - base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; - base64 += chars[bytes[i + 2] & 63]; - } - - if ((len % 3) === 2) { - base64 = base64.substring(0, base64.length - 1) + "="; - } else if (len % 3 === 1) { - base64 = base64.substring(0, base64.length - 2) + "=="; - } - - return base64; - }; - - exports.decode = function(base64) { - var bufferLength = base64.length * 0.75, - len = base64.length, i, p = 0, - encoded1, encoded2, encoded3, encoded4; - - if (base64[base64.length - 1] === "=") { - bufferLength--; - if (base64[base64.length - 2] === "=") { - bufferLength--; - } - } - - var arraybuffer = new ArrayBuffer(bufferLength), - bytes = new Uint8Array(arraybuffer); - - for (i = 0; i < len; i+=4) { - encoded1 = lookup[base64.charCodeAt(i)]; - encoded2 = lookup[base64.charCodeAt(i+1)]; - encoded3 = lookup[base64.charCodeAt(i+2)]; - encoded4 = lookup[base64.charCodeAt(i+3)]; - - bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); - bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); - bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); - } - - return arraybuffer; - }; -})(); diff --git a/web/node_modules/base64-arraybuffer/package.json b/web/node_modules/base64-arraybuffer/package.json deleted file mode 100644 index 7f62ae9..0000000 --- a/web/node_modules/base64-arraybuffer/package.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "_args": [ - [ - "base64-arraybuffer@0.1.5", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "base64-arraybuffer@0.1.5", - "_id": "base64-arraybuffer@0.1.5", - "_inBundle": false, - "_integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "_location": "/base64-arraybuffer", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "base64-arraybuffer@0.1.5", - "name": "base64-arraybuffer", - "escapedName": "base64-arraybuffer", - "rawSpec": "0.1.5", - "saveSpec": null, - "fetchSpec": "0.1.5" - }, - "_requiredBy": [ - "/engine.io-parser" - ], - "_resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "_spec": "0.1.5", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "Niklas von Hertzen", - "email": "niklasvh@gmail.com", - "url": "http://hertzen.com" - }, - "bugs": { - "url": "https://github.com/niklasvh/base64-arraybuffer/issues" - }, - "description": "Encode/decode base64 data into ArrayBuffers", - "devDependencies": { - "grunt": "^0.4.5", - "grunt-cli": "^0.1.13", - "grunt-contrib-jshint": "^0.11.2", - "grunt-contrib-nodeunit": "^0.4.1", - "grunt-contrib-watch": "^0.6.1" - }, - "engines": { - "node": ">= 0.6.0" - }, - "homepage": "https://github.com/niklasvh/base64-arraybuffer", - "keywords": [], - "licenses": [ - { - "type": "MIT", - "url": "https://github.com/niklasvh/base64-arraybuffer/blob/master/LICENSE-MIT" - } - ], - "main": "lib/base64-arraybuffer", - "name": "base64-arraybuffer", - "repository": { - "type": "git", - "url": "git+https://github.com/niklasvh/base64-arraybuffer.git" - }, - "scripts": { - "test": "grunt nodeunit" - }, - "version": "0.1.5" -} diff --git a/web/node_modules/base64id/.npmignore b/web/node_modules/base64id/.npmignore deleted file mode 100644 index 39e9864..0000000 --- a/web/node_modules/base64id/.npmignore +++ /dev/null @@ -1,3 +0,0 @@ -support -test -examples diff --git a/web/node_modules/base64id/README.md b/web/node_modules/base64id/README.md deleted file mode 100644 index b4361c1..0000000 --- a/web/node_modules/base64id/README.md +++ /dev/null @@ -1,18 +0,0 @@ -base64id -======== - -Node.js module that generates a base64 id. - -Uses crypto.randomBytes when available, falls back to unsafe methods for node.js <= 0.4. - -To increase performance, random bytes are buffered to minimize the number of synchronous calls to crypto.randomBytes. - -## Installation - - $ npm install mongoose - -## Usage - - var base64id = require('base64id'); - - var id = base64id.generateId(); diff --git a/web/node_modules/base64id/lib/base64id.js b/web/node_modules/base64id/lib/base64id.js deleted file mode 100644 index f688159..0000000 --- a/web/node_modules/base64id/lib/base64id.js +++ /dev/null @@ -1,103 +0,0 @@ -/*! - * base64id v0.1.0 - */ - -/** - * Module dependencies - */ - -var crypto = require('crypto'); - -/** - * Constructor - */ - -var Base64Id = function() { }; - -/** - * Get random bytes - * - * Uses a buffer if available, falls back to crypto.randomBytes - */ - -Base64Id.prototype.getRandomBytes = function(bytes) { - - var BUFFER_SIZE = 4096 - var self = this; - - bytes = bytes || 12; - - if (bytes > BUFFER_SIZE) { - return crypto.randomBytes(bytes); - } - - var bytesInBuffer = parseInt(BUFFER_SIZE/bytes); - var threshold = parseInt(bytesInBuffer*0.85); - - if (!threshold) { - return crypto.randomBytes(bytes); - } - - if (this.bytesBufferIndex == null) { - this.bytesBufferIndex = -1; - } - - if (this.bytesBufferIndex == bytesInBuffer) { - this.bytesBuffer = null; - this.bytesBufferIndex = -1; - } - - // No buffered bytes available or index above threshold - if (this.bytesBufferIndex == -1 || this.bytesBufferIndex > threshold) { - - if (!this.isGeneratingBytes) { - this.isGeneratingBytes = true; - crypto.randomBytes(BUFFER_SIZE, function(err, bytes) { - self.bytesBuffer = bytes; - self.bytesBufferIndex = 0; - self.isGeneratingBytes = false; - }); - } - - // Fall back to sync call when no buffered bytes are available - if (this.bytesBufferIndex == -1) { - return crypto.randomBytes(bytes); - } - } - - var result = this.bytesBuffer.slice(bytes*this.bytesBufferIndex, bytes*(this.bytesBufferIndex+1)); - this.bytesBufferIndex++; - - return result; -} - -/** - * Generates a base64 id - * - * (Original version from socket.io ) - */ - -Base64Id.prototype.generateId = function () { - var rand = new Buffer(15); // multiple of 3 for base64 - if (!rand.writeInt32BE) { - return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString() - + Math.abs(Math.random() * Math.random() * Date.now() | 0).toString(); - } - this.sequenceNumber = (this.sequenceNumber + 1) | 0; - rand.writeInt32BE(this.sequenceNumber, 11); - if (crypto.randomBytes) { - this.getRandomBytes(12).copy(rand); - } else { - // not secure for node 0.4 - [0, 4, 8].forEach(function(i) { - rand.writeInt32BE(Math.random() * Math.pow(2, 32) | 0, i); - }); - } - return rand.toString('base64').replace(/\//g, '_').replace(/\+/g, '-'); -}; - -/** - * Export - */ - -exports = module.exports = new Base64Id(); diff --git a/web/node_modules/base64id/package.json b/web/node_modules/base64id/package.json deleted file mode 100644 index 2df6ea7..0000000 --- a/web/node_modules/base64id/package.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "_args": [ - [ - "base64id@0.1.0", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "base64id@0.1.0", - "_id": "base64id@0.1.0", - "_inBundle": false, - "_integrity": "sha1-As4P3u4M709ACA4ec+g08LG/zj8=", - "_location": "/base64id", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "base64id@0.1.0", - "name": "base64id", - "escapedName": "base64id", - "rawSpec": "0.1.0", - "saveSpec": null, - "fetchSpec": "0.1.0" - }, - "_requiredBy": [ - "/engine.io" - ], - "_resolved": "https://registry.npmjs.org/base64id/-/base64id-0.1.0.tgz", - "_spec": "0.1.0", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "Kristian Faeldt", - "email": "faeldt_kristian@cyberagent.co.jp" - }, - "bugs": { - "url": "https://github.com/faeldt/base64id/issues" - }, - "description": "Generates a base64 id", - "engines": { - "node": ">= 0.4.0" - }, - "homepage": "https://github.com/faeldt/base64id#readme", - "main": "./lib/base64id.js", - "name": "base64id", - "repository": { - "type": "git", - "url": "git+https://github.com/faeldt/base64id.git" - }, - "version": "0.1.0" -} diff --git a/web/node_modules/batch/.npmignore b/web/node_modules/batch/.npmignore deleted file mode 100644 index f1250e5..0000000 --- a/web/node_modules/batch/.npmignore +++ /dev/null @@ -1,4 +0,0 @@ -support -test -examples -*.sock diff --git a/web/node_modules/batch/History.md b/web/node_modules/batch/History.md deleted file mode 100644 index 424324a..0000000 --- a/web/node_modules/batch/History.md +++ /dev/null @@ -1,71 +0,0 @@ - -0.5.1 / 2014-06-19 -================== - - * add repository field to readme (exciting) - -0.5.0 / 2013-07-29 -================== - - * add `.throws(true)` to opt-in to responding with an array of error objects - * make `new` optional - -0.4.0 / 2013-06-05 -================== - - * add catching of immediate callback errors - -0.3.2 / 2013-03-15 -================== - - * remove Emitter call in constructor - -0.3.1 / 2013-03-13 -================== - - * add Emitter() mixin for client. Closes #8 - -0.3.0 / 2013-03-13 -================== - - * add component.json - * add result example - * add .concurrency support - * add concurrency example - * add parallel example - -0.2.1 / 2012-11-08 -================== - - * add .start, .end, and .duration properties - * change dependencies to devDependencies - -0.2.0 / 2012-10-04 -================== - - * add progress events. Closes #5 (__BREAKING CHANGE__) - -0.1.1 / 2012-07-03 -================== - - * change "complete" event to "progress" - -0.1.0 / 2012-07-03 -================== - - * add Emitter inheritance and emit "complete" [burcu] - -0.0.3 / 2012-06-02 -================== - - * Callback results should be in the order of the queued functions. - -0.0.2 / 2012-02-12 -================== - - * any node - -0.0.1 / 2010-01-03 -================== - - * Initial release diff --git a/web/node_modules/batch/Makefile b/web/node_modules/batch/Makefile deleted file mode 100644 index 634e372..0000000 --- a/web/node_modules/batch/Makefile +++ /dev/null @@ -1,6 +0,0 @@ - -test: - @./node_modules/.bin/mocha \ - --require should - -.PHONY: test \ No newline at end of file diff --git a/web/node_modules/batch/Readme.md b/web/node_modules/batch/Readme.md deleted file mode 100644 index f2345c6..0000000 --- a/web/node_modules/batch/Readme.md +++ /dev/null @@ -1,74 +0,0 @@ - -# batch - - Simple async batch with concurrency control and progress reporting. - -## Installation - -``` -$ npm install batch -``` - -## API - -```js -var Batch = require('batch') - , batch = new Batch; - -batch.concurrency(4); - -ids.forEach(function(id){ - batch.push(function(done){ - User.get(id, done); - }); -}); - -batch.on('progress', function(e){ - -}); - -batch.end(function(err, users){ - -}); -``` - -### Progress events - - Contain the "job" index, response value, duration information, and completion data. - -```js -{ index: 1, - value: 'bar', - pending: 2, - total: 3, - complete: 2, - percent: 66, - start: Thu Oct 04 2012 12:25:53 GMT-0700 (PDT), - end: Thu Oct 04 2012 12:25:53 GMT-0700 (PDT), - duration: 0 } -``` - -## License - -(The MIT License) - -Copyright (c) 2013 TJ Holowaychuk <tj@vision-media.ca> - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/web/node_modules/batch/component.json b/web/node_modules/batch/component.json deleted file mode 100644 index 9bd3e45..0000000 --- a/web/node_modules/batch/component.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "batch", - "repo": "visionmedia/batch", - "description": "Async task batching", - "version": "0.5.2", - "keywords": ["batch", "async", "utility", "concurrency", "concurrent"], - "dependencies": { - "component/emitter": "*" - }, - "development": {}, - "scripts": [ - "index.js" - ] -} diff --git a/web/node_modules/batch/index.js b/web/node_modules/batch/index.js deleted file mode 100644 index c2cbe46..0000000 --- a/web/node_modules/batch/index.js +++ /dev/null @@ -1,158 +0,0 @@ -/** - * Module dependencies. - */ - -try { - var EventEmitter = require('events').EventEmitter; -} catch (err) { - var Emitter = require('emitter'); -} - -/** - * Noop. - */ - -function noop(){} - -/** - * Expose `Batch`. - */ - -module.exports = Batch; - -/** - * Create a new Batch. - */ - -function Batch() { - if (!(this instanceof Batch)) return new Batch; - this.fns = []; - this.concurrency(Infinity); - this.throws(true); - for (var i = 0, len = arguments.length; i < len; ++i) { - this.push(arguments[i]); - } -} - -/** - * Inherit from `EventEmitter.prototype`. - */ - -if (EventEmitter) { - Batch.prototype.__proto__ = EventEmitter.prototype; -} else { - Emitter(Batch.prototype); -} - -/** - * Set concurrency to `n`. - * - * @param {Number} n - * @return {Batch} - * @api public - */ - -Batch.prototype.concurrency = function(n){ - this.n = n; - return this; -}; - -/** - * Queue a function. - * - * @param {Function} fn - * @return {Batch} - * @api public - */ - -Batch.prototype.push = function(fn){ - this.fns.push(fn); - return this; -}; - -/** - * Set wether Batch will or will not throw up. - * - * @param {Boolean} throws - * @return {Batch} - * @api public - */ -Batch.prototype.throws = function(throws) { - this.e = !!throws; - return this; -}; - -/** - * Execute all queued functions in parallel, - * executing `cb(err, results)`. - * - * @param {Function} cb - * @return {Batch} - * @api public - */ - -Batch.prototype.end = function(cb){ - var self = this - , total = this.fns.length - , pending = total - , results = [] - , errors = [] - , cb = cb || noop - , fns = this.fns - , max = this.n - , throws = this.e - , index = 0 - , done; - - // empty - if (!fns.length) return cb(null, results); - - // process - function next() { - var i = index++; - var fn = fns[i]; - if (!fn) return; - var start = new Date; - - try { - fn(callback); - } catch (err) { - callback(err); - } - - function callback(err, res){ - if (done) return; - if (err && throws) return done = true, cb(err); - var complete = total - pending + 1; - var end = new Date; - - results[i] = res; - errors[i] = err; - - self.emit('progress', { - index: i, - value: res, - error: err, - pending: pending, - total: total, - complete: complete, - percent: complete / total * 100 | 0, - start: start, - end: end, - duration: end - start - }); - - if (--pending) next(); - else if(!throws) cb(errors, results); - else cb(null, results); - } - } - - // concurrency - for (var i = 0; i < fns.length; i++) { - if (i == max) break; - next(); - } - - return this; -}; diff --git a/web/node_modules/batch/package.json b/web/node_modules/batch/package.json deleted file mode 100644 index a8935a0..0000000 --- a/web/node_modules/batch/package.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "_args": [ - [ - "batch@0.5.3", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "batch@0.5.3", - "_id": "batch@0.5.3", - "_inBundle": false, - "_integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=", - "_location": "/batch", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "batch@0.5.3", - "name": "batch", - "escapedName": "batch", - "rawSpec": "0.5.3", - "saveSpec": null, - "fetchSpec": "0.5.3" - }, - "_requiredBy": [ - "/serve-index" - ], - "_resolved": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", - "_spec": "0.5.3", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "TJ Holowaychuk", - "email": "tj@vision-media.ca" - }, - "browser": { - "emitter": "events" - }, - "bugs": { - "url": "https://github.com/visionmedia/batch/issues" - }, - "description": "Simple async batch", - "devDependencies": { - "mocha": "*", - "should": "*" - }, - "homepage": "https://github.com/visionmedia/batch#readme", - "licenses": [ - { - "type": "MIT" - } - ], - "main": "index", - "name": "batch", - "repository": { - "type": "git", - "url": "git+https://github.com/visionmedia/batch.git" - }, - "version": "0.5.3" -} diff --git a/web/node_modules/bcrypt-pbkdf/README.md b/web/node_modules/bcrypt-pbkdf/README.md deleted file mode 100644 index 1201809..0000000 --- a/web/node_modules/bcrypt-pbkdf/README.md +++ /dev/null @@ -1,39 +0,0 @@ -Port of the OpenBSD `bcrypt_pbkdf` function to pure Javascript. `npm`-ified -version of [Devi Mandiri's port] -(https://github.com/devi/tmp/blob/master/js/bcrypt_pbkdf.js), -with some minor performance improvements. The code is copied verbatim (and -un-styled) from Devi's work. - -This product includes software developed by Niels Provos. - -## API - -### `bcrypt_pbkdf.pbkdf(pass, passlen, salt, saltlen, key, keylen, rounds)` - -Derive a cryptographic key of arbitrary length from a given password and salt, -using the OpenBSD `bcrypt_pbkdf` function. This is a combination of Blowfish and -SHA-512. - -See [this article](http://www.tedunangst.com/flak/post/bcrypt-pbkdf) for -further information. - -Parameters: - - * `pass`, a Uint8Array of length `passlen` - * `passlen`, an integer Number - * `salt`, a Uint8Array of length `saltlen` - * `saltlen`, an integer Number - * `key`, a Uint8Array of length `keylen`, will be filled with output - * `keylen`, an integer Number - * `rounds`, an integer Number, number of rounds of the PBKDF to run - -### `bcrypt_pbkdf.hash(sha2pass, sha2salt, out)` - -Calculate a Blowfish hash, given SHA2-512 output of a password and salt. Used as -part of the inner round function in the PBKDF. - -Parameters: - - * `sha2pass`, a Uint8Array of length 64 - * `sha2salt`, a Uint8Array of length 64 - * `out`, a Uint8Array of length 32, will be filled with output diff --git a/web/node_modules/bcrypt-pbkdf/index.js b/web/node_modules/bcrypt-pbkdf/index.js deleted file mode 100644 index b1b5ad4..0000000 --- a/web/node_modules/bcrypt-pbkdf/index.js +++ /dev/null @@ -1,556 +0,0 @@ -'use strict'; - -var crypto_hash_sha512 = require('tweetnacl').lowlevel.crypto_hash; - -/* - * This file is a 1:1 port from the OpenBSD blowfish.c and bcrypt_pbkdf.c. As a - * result, it retains the original copyright and license. The two files are - * under slightly different (but compatible) licenses, and are here combined in - * one file. - * - * Credit for the actual porting work goes to: - * Devi Mandiri - */ - -/* - * The Blowfish portions are under the following license: - * - * Blowfish block cipher for OpenBSD - * Copyright 1997 Niels Provos - * All rights reserved. - * - * Implementation advice by David Mazieres . - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * The bcrypt_pbkdf portions are under the following license: - * - * Copyright (c) 2013 Ted Unangst - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Performance improvements (Javascript-specific): - * - * Copyright 2016, Joyent Inc - * Author: Alex Wilson - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -// Ported from OpenBSD bcrypt_pbkdf.c v1.9 - -var BLF_J = 0; - -var Blowfish = function() { - this.S = [ - new Uint32Array([ - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, - 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, - 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, - 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, - 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, - 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, - 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, - 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, - 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, - 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, - 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, - 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, - 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, - 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, - 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, - 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, - 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, - 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, - 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, - 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, - 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, - 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, - 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, - 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, - 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, - 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, - 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, - 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, - 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, - 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, - 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, - 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, - 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, - 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, - 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, - 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, - 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, - 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, - 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, - 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, - 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, - 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, - 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, - 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, - 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, - 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, - 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, - 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, - 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, - 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, - 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, - 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, - 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, - 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, - 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, - 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, - 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, - 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, - 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, - 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, - 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, - 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a]), - new Uint32Array([ - 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, - 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, - 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, - 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, - 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, - 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, - 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, - 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, - 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, - 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, - 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, - 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, - 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, - 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, - 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, - 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, - 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, - 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, - 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, - 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, - 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, - 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, - 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, - 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, - 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, - 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, - 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, - 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, - 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, - 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, - 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, - 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, - 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, - 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, - 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, - 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, - 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, - 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, - 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, - 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, - 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, - 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, - 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, - 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, - 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, - 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, - 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, - 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, - 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, - 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, - 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, - 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, - 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, - 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, - 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, - 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, - 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, - 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, - 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, - 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, - 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, - 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7]), - new Uint32Array([ - 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, - 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, - 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, - 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, - 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, - 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, - 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, - 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, - 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, - 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, - 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, - 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, - 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, - 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, - 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, - 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, - 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, - 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, - 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, - 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, - 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, - 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, - 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, - 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, - 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, - 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, - 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, - 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, - 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, - 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, - 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, - 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, - 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, - 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, - 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, - 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, - 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, - 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, - 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, - 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, - 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, - 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, - 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, - 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, - 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, - 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, - 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, - 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, - 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, - 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, - 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, - 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, - 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, - 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, - 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, - 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, - 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, - 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, - 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, - 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, - 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, - 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0]), - new Uint32Array([ - 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, - 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, - 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, - 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, - 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, - 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, - 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, - 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, - 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, - 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, - 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, - 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, - 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, - 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, - 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, - 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, - 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, - 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, - 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, - 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, - 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, - 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, - 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, - 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, - 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, - 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, - 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, - 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, - 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, - 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, - 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, - 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, - 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, - 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, - 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, - 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, - 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, - 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, - 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, - 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, - 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, - 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, - 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, - 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, - 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, - 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, - 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, - 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, - 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, - 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, - 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, - 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, - 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, - 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, - 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, - 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, - 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, - 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, - 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, - 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, - 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, - 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6]) - ]; - this.P = new Uint32Array([ - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, - 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, - 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, - 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, - 0x9216d5d9, 0x8979fb1b]); -}; - -function F(S, x8, i) { - return (((S[0][x8[i+3]] + - S[1][x8[i+2]]) ^ - S[2][x8[i+1]]) + - S[3][x8[i]]); -}; - -Blowfish.prototype.encipher = function(x, x8) { - if (x8 === undefined) { - x8 = new Uint8Array(x.buffer); - if (x.byteOffset !== 0) - x8 = x8.subarray(x.byteOffset); - } - x[0] ^= this.P[0]; - for (var i = 1; i < 16; i += 2) { - x[1] ^= F(this.S, x8, 0) ^ this.P[i]; - x[0] ^= F(this.S, x8, 4) ^ this.P[i+1]; - } - var t = x[0]; - x[0] = x[1] ^ this.P[17]; - x[1] = t; -}; - -Blowfish.prototype.decipher = function(x) { - var x8 = new Uint8Array(x.buffer); - if (x.byteOffset !== 0) - x8 = x8.subarray(x.byteOffset); - x[0] ^= this.P[17]; - for (var i = 16; i > 0; i -= 2) { - x[1] ^= F(this.S, x8, 0) ^ this.P[i]; - x[0] ^= F(this.S, x8, 4) ^ this.P[i-1]; - } - var t = x[0]; - x[0] = x[1] ^ this.P[0]; - x[1] = t; -}; - -function stream2word(data, databytes){ - var i, temp = 0; - for (i = 0; i < 4; i++, BLF_J++) { - if (BLF_J >= databytes) BLF_J = 0; - temp = (temp << 8) | data[BLF_J]; - } - return temp; -}; - -Blowfish.prototype.expand0state = function(key, keybytes) { - var d = new Uint32Array(2), i, k; - var d8 = new Uint8Array(d.buffer); - - for (i = 0, BLF_J = 0; i < 18; i++) { - this.P[i] ^= stream2word(key, keybytes); - } - BLF_J = 0; - - for (i = 0; i < 18; i += 2) { - this.encipher(d, d8); - this.P[i] = d[0]; - this.P[i+1] = d[1]; - } - - for (i = 0; i < 4; i++) { - for (k = 0; k < 256; k += 2) { - this.encipher(d, d8); - this.S[i][k] = d[0]; - this.S[i][k+1] = d[1]; - } - } -}; - -Blowfish.prototype.expandstate = function(data, databytes, key, keybytes) { - var d = new Uint32Array(2), i, k; - - for (i = 0, BLF_J = 0; i < 18; i++) { - this.P[i] ^= stream2word(key, keybytes); - } - - for (i = 0, BLF_J = 0; i < 18; i += 2) { - d[0] ^= stream2word(data, databytes); - d[1] ^= stream2word(data, databytes); - this.encipher(d); - this.P[i] = d[0]; - this.P[i+1] = d[1]; - } - - for (i = 0; i < 4; i++) { - for (k = 0; k < 256; k += 2) { - d[0] ^= stream2word(data, databytes); - d[1] ^= stream2word(data, databytes); - this.encipher(d); - this.S[i][k] = d[0]; - this.S[i][k+1] = d[1]; - } - } - BLF_J = 0; -}; - -Blowfish.prototype.enc = function(data, blocks) { - for (var i = 0; i < blocks; i++) { - this.encipher(data.subarray(i*2)); - } -}; - -Blowfish.prototype.dec = function(data, blocks) { - for (var i = 0; i < blocks; i++) { - this.decipher(data.subarray(i*2)); - } -}; - -var BCRYPT_BLOCKS = 8, - BCRYPT_HASHSIZE = 32; - -function bcrypt_hash(sha2pass, sha2salt, out) { - var state = new Blowfish(), - cdata = new Uint32Array(BCRYPT_BLOCKS), i, - ciphertext = new Uint8Array([79,120,121,99,104,114,111,109,97,116,105, - 99,66,108,111,119,102,105,115,104,83,119,97,116,68,121,110,97,109, - 105,116,101]); //"OxychromaticBlowfishSwatDynamite" - - state.expandstate(sha2salt, 64, sha2pass, 64); - for (i = 0; i < 64; i++) { - state.expand0state(sha2salt, 64); - state.expand0state(sha2pass, 64); - } - - for (i = 0; i < BCRYPT_BLOCKS; i++) - cdata[i] = stream2word(ciphertext, ciphertext.byteLength); - for (i = 0; i < 64; i++) - state.enc(cdata, cdata.byteLength / 8); - - for (i = 0; i < BCRYPT_BLOCKS; i++) { - out[4*i+3] = cdata[i] >>> 24; - out[4*i+2] = cdata[i] >>> 16; - out[4*i+1] = cdata[i] >>> 8; - out[4*i+0] = cdata[i]; - } -}; - -function bcrypt_pbkdf(pass, passlen, salt, saltlen, key, keylen, rounds) { - var sha2pass = new Uint8Array(64), - sha2salt = new Uint8Array(64), - out = new Uint8Array(BCRYPT_HASHSIZE), - tmpout = new Uint8Array(BCRYPT_HASHSIZE), - countsalt = new Uint8Array(saltlen+4), - i, j, amt, stride, dest, count, - origkeylen = keylen; - - if (rounds < 1) - return -1; - if (passlen === 0 || saltlen === 0 || keylen === 0 || - keylen > (out.byteLength * out.byteLength) || saltlen > (1<<20)) - return -1; - - stride = Math.floor((keylen + out.byteLength - 1) / out.byteLength); - amt = Math.floor((keylen + stride - 1) / stride); - - for (i = 0; i < saltlen; i++) - countsalt[i] = salt[i]; - - crypto_hash_sha512(sha2pass, pass, passlen); - - for (count = 1; keylen > 0; count++) { - countsalt[saltlen+0] = count >>> 24; - countsalt[saltlen+1] = count >>> 16; - countsalt[saltlen+2] = count >>> 8; - countsalt[saltlen+3] = count; - - crypto_hash_sha512(sha2salt, countsalt, saltlen + 4); - bcrypt_hash(sha2pass, sha2salt, tmpout); - for (i = out.byteLength; i--;) - out[i] = tmpout[i]; - - for (i = 1; i < rounds; i++) { - crypto_hash_sha512(sha2salt, tmpout, tmpout.byteLength); - bcrypt_hash(sha2pass, sha2salt, tmpout); - for (j = 0; j < out.byteLength; j++) - out[j] ^= tmpout[j]; - } - - amt = Math.min(amt, keylen); - for (i = 0; i < amt; i++) { - dest = i * stride + (count - 1); - if (dest >= origkeylen) - break; - key[dest] = out[i]; - } - keylen -= i; - } - - return 0; -}; - -module.exports = { - BLOCKS: BCRYPT_BLOCKS, - HASHSIZE: BCRYPT_HASHSIZE, - hash: bcrypt_hash, - pbkdf: bcrypt_pbkdf -}; diff --git a/web/node_modules/bcrypt-pbkdf/package.json b/web/node_modules/bcrypt-pbkdf/package.json deleted file mode 100644 index 466b38b..0000000 --- a/web/node_modules/bcrypt-pbkdf/package.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "_args": [ - [ - "bcrypt-pbkdf@1.0.1", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "bcrypt-pbkdf@1.0.1", - "_id": "bcrypt-pbkdf@1.0.1", - "_inBundle": false, - "_integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "_location": "/bcrypt-pbkdf", - "_optional": true, - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "bcrypt-pbkdf@1.0.1", - "name": "bcrypt-pbkdf", - "escapedName": "bcrypt-pbkdf", - "rawSpec": "1.0.1", - "saveSpec": null, - "fetchSpec": "1.0.1" - }, - "_requiredBy": [ - "/sshpk" - ], - "_resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "_spec": "1.0.1", - "_where": "/home/treharne/Documents/web/cdt-py", - "dependencies": { - "tweetnacl": "^0.14.3" - }, - "description": "Port of the OpenBSD bcrypt_pbkdf function to pure JS", - "devDependencies": {}, - "license": "BSD-3-Clause", - "main": "index.js", - "name": "bcrypt-pbkdf", - "version": "1.0.1" -} diff --git a/web/node_modules/beeper/index.js b/web/node_modules/beeper/index.js deleted file mode 100644 index 2bf6503..0000000 --- a/web/node_modules/beeper/index.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; - -var BEEP_DELAY = 500; - -function beep() { - process.stdout.write('\u0007'); -} - -function melodicalBeep(val, cb) { - if (val.length === 0) { - cb(); - return; - } - - setTimeout(function () { - if (val.shift() === '*') { - beep(); - } - - melodicalBeep(val, cb); - }, BEEP_DELAY); -} - -module.exports = function (val, cb) { - if (!process.stdout.isTTY || - process.argv.indexOf('--no-beep') !== -1 || - process.argv.indexOf('--beep=false') !== -1) { - return; - } - - cb = cb || function () {}; - - if (val === parseInt(val)) { - if (val < 0) { - throw new TypeError('Negative numbers are not accepted'); - } - - if (val === 0) { - cb(); - return; - } - - for (var i = 0; i < val; i++) { - setTimeout(function (i) { - beep(); - - if (i === val - 1) { - cb(); - } - }, BEEP_DELAY * i, i); - } - } else if (!val) { - beep(); - cb(); - } else if (typeof val === 'string') { - melodicalBeep(val.split(''), cb); - } else { - throw new TypeError('Not an accepted type'); - } -}; diff --git a/web/node_modules/beeper/license b/web/node_modules/beeper/license deleted file mode 100644 index 654d0bf..0000000 --- a/web/node_modules/beeper/license +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/web/node_modules/beeper/package.json b/web/node_modules/beeper/package.json deleted file mode 100644 index 7f17ec9..0000000 --- a/web/node_modules/beeper/package.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "_args": [ - [ - "beeper@1.1.1", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "beeper@1.1.1", - "_id": "beeper@1.1.1", - "_inBundle": false, - "_integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "_location": "/beeper", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "beeper@1.1.1", - "name": "beeper", - "escapedName": "beeper", - "rawSpec": "1.1.1", - "saveSpec": null, - "fetchSpec": "1.1.1" - }, - "_requiredBy": [ - "/gulp-util" - ], - "_resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "_spec": "1.1.1", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "Sindre Sorhus", - "email": "sindresorhus@gmail.com", - "url": "sindresorhus.com" - }, - "bugs": { - "url": "https://github.com/sindresorhus/beeper/issues" - }, - "description": "Make your terminal beep", - "devDependencies": { - "hooker": "^0.2.3", - "tape": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "files": [ - "index.js" - ], - "homepage": "https://github.com/sindresorhus/beeper#readme", - "keywords": [ - "beep", - "beeper", - "boop", - "terminal", - "term", - "cli", - "console", - "ding", - "ping", - "alert", - "gulpfriendly" - ], - "license": "MIT", - "name": "beeper", - "repository": { - "type": "git", - "url": "git+https://github.com/sindresorhus/beeper.git" - }, - "scripts": { - "test": "node test.js" - }, - "version": "1.1.1" -} diff --git a/web/node_modules/beeper/readme.md b/web/node_modules/beeper/readme.md deleted file mode 100644 index 55bdd52..0000000 --- a/web/node_modules/beeper/readme.md +++ /dev/null @@ -1,55 +0,0 @@ -# beeper [![Build Status](https://travis-ci.org/sindresorhus/beeper.svg?branch=master)](https://travis-ci.org/sindresorhus/beeper) - -> Make your terminal beep - -![](https://cloud.githubusercontent.com/assets/170270/5261236/f8471100-7a49-11e4-81af-96cd09a522d9.gif) - -Useful as an attention grabber e.g. when an error happens. - - -## Install - -``` -$ npm install --save beeper -``` - - -## Usage - -```js -var beeper = require('beeper'); - -beeper(); -// beep one time - -beeper(3); -// beep three times - -beeper('****-*-*'); -// beep, beep, beep, beep, pause, beep, pause, beep -``` - - -## API - -It will not beep if stdout is not TTY or if the user supplies the `--no-beep` flag. - -### beeper([count|melody], [callback]) - -#### count - -Type: `number` -Default: `1` - -How many times you want it to beep. - -#### melody - -Type: `string` - -Construct your own melody by supplying a string of `*` for beep `-` for pause. - - -## License - -MIT © [Sindre Sorhus](http://sindresorhus.com) diff --git a/web/node_modules/better-assert/.npmignore b/web/node_modules/better-assert/.npmignore deleted file mode 100644 index f1250e5..0000000 --- a/web/node_modules/better-assert/.npmignore +++ /dev/null @@ -1,4 +0,0 @@ -support -test -examples -*.sock diff --git a/web/node_modules/better-assert/History.md b/web/node_modules/better-assert/History.md deleted file mode 100644 index cbb579b..0000000 --- a/web/node_modules/better-assert/History.md +++ /dev/null @@ -1,15 +0,0 @@ - -1.0.0 / 2013-02-03 -================== - - * Stop using the removed magic __stack global getter - -0.1.0 / 2012-10-04 -================== - - * add throwing of AssertionError for test frameworks etc - -0.0.1 / 2010-01-03 -================== - - * Initial release diff --git a/web/node_modules/better-assert/Makefile b/web/node_modules/better-assert/Makefile deleted file mode 100644 index 36a3ed7..0000000 --- a/web/node_modules/better-assert/Makefile +++ /dev/null @@ -1,5 +0,0 @@ - -test: - @echo "populate me" - -.PHONY: test \ No newline at end of file diff --git a/web/node_modules/better-assert/Readme.md b/web/node_modules/better-assert/Readme.md deleted file mode 100644 index d8d3a63..0000000 --- a/web/node_modules/better-assert/Readme.md +++ /dev/null @@ -1,61 +0,0 @@ - -# better-assert - - Better c-style assertions using [callsite](https://github.com/visionmedia/callsite) for - self-documenting failure messages. - -## Installation - - $ npm install better-assert - -## Example - - By default assertions are enabled, however the __NO_ASSERT__ environment variable - will deactivate them when truthy. - -```js -var assert = require('better-assert'); - -test(); - -function test() { - var user = { name: 'tobi' }; - assert('tobi' == user.name); - assert('number' == typeof user.age); -} - -AssertionError: 'number' == typeof user.age - at test (/Users/tj/projects/better-assert/example.js:9:3) - at Object. (/Users/tj/projects/better-assert/example.js:4:1) - at Module._compile (module.js:449:26) - at Object.Module._extensions..js (module.js:467:10) - at Module.load (module.js:356:32) - at Function.Module._load (module.js:312:12) - at Module.runMain (module.js:492:10) - at process.startup.processNextTick.process._tickCallback (node.js:244:9) -``` - -## License - -(The MIT License) - -Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca> - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/web/node_modules/better-assert/example.js b/web/node_modules/better-assert/example.js deleted file mode 100644 index 688c29e..0000000 --- a/web/node_modules/better-assert/example.js +++ /dev/null @@ -1,10 +0,0 @@ - -var assert = require('./'); - -test(); - -function test() { - var user = { name: 'tobi' }; - assert('tobi' == user.name); - assert('number' == typeof user.age); -} \ No newline at end of file diff --git a/web/node_modules/better-assert/index.js b/web/node_modules/better-assert/index.js deleted file mode 100644 index fd1c9b7..0000000 --- a/web/node_modules/better-assert/index.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Module dependencies. - */ - -var AssertionError = require('assert').AssertionError - , callsite = require('callsite') - , fs = require('fs') - -/** - * Expose `assert`. - */ - -module.exports = process.env.NO_ASSERT - ? function(){} - : assert; - -/** - * Assert the given `expr`. - */ - -function assert(expr) { - if (expr) return; - - var stack = callsite(); - var call = stack[1]; - var file = call.getFileName(); - var lineno = call.getLineNumber(); - var src = fs.readFileSync(file, 'utf8'); - var line = src.split('\n')[lineno-1]; - var src = line.match(/assert\((.*)\)/)[1]; - - var err = new AssertionError({ - message: src, - stackStartFunction: stack[0].getFunction() - }); - - throw err; -} diff --git a/web/node_modules/better-assert/package.json b/web/node_modules/better-assert/package.json deleted file mode 100644 index 74b473b..0000000 --- a/web/node_modules/better-assert/package.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "_args": [ - [ - "better-assert@1.0.2", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "better-assert@1.0.2", - "_id": "better-assert@1.0.2", - "_inBundle": false, - "_integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "_location": "/better-assert", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "better-assert@1.0.2", - "name": "better-assert", - "escapedName": "better-assert", - "rawSpec": "1.0.2", - "saveSpec": null, - "fetchSpec": "1.0.2" - }, - "_requiredBy": [ - "/parsejson", - "/parseqs", - "/parseuri" - ], - "_resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "_spec": "1.0.2", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "TJ Holowaychuk", - "email": "tj@vision-media.ca" - }, - "bugs": { - "url": "https://github.com/visionmedia/better-assert/issues" - }, - "contributors": [ - { - "name": "TonyHe", - "email": "coolhzb@163.com" - }, - { - "name": "ForbesLindesay" - } - ], - "dependencies": { - "callsite": "1.0.0" - }, - "description": "Better assertions for node, reporting the expr, filename, lineno etc", - "engines": { - "node": "*" - }, - "homepage": "https://github.com/visionmedia/better-assert#readme", - "keywords": [ - "assert", - "stack", - "trace", - "debug" - ], - "main": "index", - "name": "better-assert", - "repository": { - "type": "git", - "url": "git+https://github.com/visionmedia/better-assert.git" - }, - "version": "1.0.2" -} diff --git a/web/node_modules/binary-extensions/binary-extensions.json b/web/node_modules/binary-extensions/binary-extensions.json deleted file mode 100644 index 774d024..0000000 --- a/web/node_modules/binary-extensions/binary-extensions.json +++ /dev/null @@ -1,242 +0,0 @@ -[ - "3ds", - "3g2", - "3gp", - "7z", - "a", - "aac", - "adp", - "ai", - "aif", - "aiff", - "alz", - "ape", - "apk", - "ar", - "arj", - "asf", - "au", - "avi", - "bak", - "bh", - "bin", - "bk", - "bmp", - "btif", - "bz2", - "bzip2", - "cab", - "caf", - "cgm", - "class", - "cmx", - "cpio", - "cr2", - "csv", - "cur", - "dat", - "dcm", - "deb", - "dex", - "djvu", - "dll", - "dmg", - "dng", - "doc", - "docm", - "docx", - "dot", - "dotm", - "dra", - "DS_Store", - "dsk", - "dts", - "dtshd", - "dvb", - "dwg", - "dxf", - "ecelp4800", - "ecelp7470", - "ecelp9600", - "egg", - "eol", - "eot", - "epub", - "exe", - "f4v", - "fbs", - "fh", - "fla", - "flac", - "fli", - "flv", - "fpx", - "fst", - "fvt", - "g3", - "gif", - "graffle", - "gz", - "gzip", - "h261", - "h263", - "h264", - "icns", - "ico", - "ief", - "img", - "ipa", - "iso", - "jar", - "jpeg", - "jpg", - "jpgv", - "jpm", - "jxr", - "key", - "ktx", - "lha", - "lvp", - "lz", - "lzh", - "lzma", - "lzo", - "m3u", - "m4a", - "m4v", - "mar", - "mdi", - "mht", - "mid", - "midi", - "mj2", - "mka", - "mkv", - "mmr", - "mng", - "mobi", - "mov", - "movie", - "mp3", - "mp4", - "mp4a", - "mpeg", - "mpg", - "mpga", - "mxu", - "nef", - "npx", - "numbers", - "o", - "oga", - "ogg", - "ogv", - "otf", - "pages", - "pbm", - "pcx", - "pdf", - "pea", - "pgm", - "pic", - "png", - "pnm", - "pot", - "potm", - "potx", - "ppa", - "ppam", - "ppm", - "pps", - "ppsm", - "ppsx", - "ppt", - "pptm", - "pptx", - "psd", - "pya", - "pyc", - "pyo", - "pyv", - "qt", - "rar", - "ras", - "raw", - "rgb", - "rip", - "rlc", - "rmf", - "rmvb", - "rtf", - "rz", - "s3m", - "s7z", - "scpt", - "sgi", - "shar", - "sil", - "sketch", - "slk", - "smv", - "so", - "sub", - "swf", - "tar", - "tbz", - "tbz2", - "tga", - "tgz", - "thmx", - "tif", - "tiff", - "tlz", - "ttc", - "ttf", - "txz", - "udf", - "uvh", - "uvi", - "uvm", - "uvp", - "uvs", - "uvu", - "viv", - "vob", - "war", - "wav", - "wax", - "wbmp", - "wdp", - "weba", - "webm", - "webp", - "whl", - "wim", - "wm", - "wma", - "wmv", - "wmx", - "woff", - "woff2", - "wvx", - "xbm", - "xif", - "xla", - "xlam", - "xls", - "xlsb", - "xlsm", - "xlsx", - "xlt", - "xltm", - "xltx", - "xm", - "xmind", - "xpi", - "xpm", - "xwd", - "xz", - "z", - "zip", - "zipx" -] diff --git a/web/node_modules/binary-extensions/license b/web/node_modules/binary-extensions/license deleted file mode 100644 index e7af2f7..0000000 --- a/web/node_modules/binary-extensions/license +++ /dev/null @@ -1,9 +0,0 @@ -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/web/node_modules/binary-extensions/package.json b/web/node_modules/binary-extensions/package.json deleted file mode 100644 index 2c2acb4..0000000 --- a/web/node_modules/binary-extensions/package.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "_args": [ - [ - "binary-extensions@1.10.0", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "binary-extensions@1.10.0", - "_id": "binary-extensions@1.10.0", - "_inBundle": false, - "_integrity": "sha1-muuabF6IY4qtFx4Wf1kAq+JINdA=", - "_location": "/binary-extensions", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "binary-extensions@1.10.0", - "name": "binary-extensions", - "escapedName": "binary-extensions", - "rawSpec": "1.10.0", - "saveSpec": null, - "fetchSpec": "1.10.0" - }, - "_requiredBy": [ - "/is-binary-path" - ], - "_resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.10.0.tgz", - "_spec": "1.10.0", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "Sindre Sorhus", - "email": "sindresorhus@gmail.com", - "url": "sindresorhus.com" - }, - "bugs": { - "url": "https://github.com/sindresorhus/binary-extensions/issues" - }, - "description": "List of binary file extensions", - "devDependencies": { - "ava": "0.16.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "files": [ - "binary-extensions.json" - ], - "homepage": "https://github.com/sindresorhus/binary-extensions#readme", - "keywords": [ - "bin", - "binary", - "ext", - "extensions", - "extension", - "file", - "json", - "list", - "array" - ], - "license": "MIT", - "main": "binary-extensions.json", - "name": "binary-extensions", - "repository": { - "type": "git", - "url": "git+https://github.com/sindresorhus/binary-extensions.git" - }, - "scripts": { - "test": "ava" - }, - "version": "1.10.0" -} diff --git a/web/node_modules/binary-extensions/readme.md b/web/node_modules/binary-extensions/readme.md deleted file mode 100644 index c0b5348..0000000 --- a/web/node_modules/binary-extensions/readme.md +++ /dev/null @@ -1,33 +0,0 @@ -# binary-extensions [![Build Status](https://travis-ci.org/sindresorhus/binary-extensions.svg?branch=master)](https://travis-ci.org/sindresorhus/binary-extensions) - -> List of binary file extensions - -The list is just a [JSON file](binary-extensions.json) and can be used wherever. - - -## Install - -``` -$ npm install binary-extensions -``` - - -## Usage - -```js -const binaryExtensions = require('binary-extensions'); - -console.log(binaryExtensions); -//=> ['3ds', '3g2', …] -``` - - -## Related - -- [is-binary-path](https://github.com/sindresorhus/is-binary-path) - Check if a filepath is a binary file -- [text-extensions](https://github.com/sindresorhus/text-extensions) - List of text file extensions - - -## License - -MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/web/node_modules/blob/.npmignore b/web/node_modules/blob/.npmignore deleted file mode 100644 index 548a368..0000000 --- a/web/node_modules/blob/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -blob.js diff --git a/web/node_modules/blob/.zuul.yml b/web/node_modules/blob/.zuul.yml deleted file mode 100644 index 380c395..0000000 --- a/web/node_modules/blob/.zuul.yml +++ /dev/null @@ -1,14 +0,0 @@ -ui: mocha-bdd -browsers: - - name: chrome - version: 8..latest - - name: firefox - version: 7..latest - - name: safari - version: 6..latest - - name: opera - version: 12.1..latest - - name: ie - version: 10..latest - - name: android - version: latest diff --git a/web/node_modules/blob/Makefile b/web/node_modules/blob/Makefile deleted file mode 100644 index 7d9601a..0000000 --- a/web/node_modules/blob/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -REPORTER = dot - -build: blob.js - -blob.js: - @./node_modules/.bin/browserify --standalone blob index.js > blob.js - -test: - @./node_modules/.bin/zuul -- test/index.js - -clean: - rm blob.js - -.PHONY: test blob.js diff --git a/web/node_modules/blob/README.md b/web/node_modules/blob/README.md deleted file mode 100644 index 6915955..0000000 --- a/web/node_modules/blob/README.md +++ /dev/null @@ -1,14 +0,0 @@ -Blob -==== - -A module that exports a constructor that uses window.Blob when available, and a BlobBuilder with any vendor prefix in other cases. If neither is available, it exports undefined. - -Usage: - -```javascript -var Blob = require('blob'); -var b = new Blob(['hi', 'constructing', 'a', 'blob']); -``` - -## Licence -MIT diff --git a/web/node_modules/blob/index.js b/web/node_modules/blob/index.js deleted file mode 100644 index cad3f84..0000000 --- a/web/node_modules/blob/index.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Create a blob builder even when vendor prefixes exist - */ - -var BlobBuilder = global.BlobBuilder - || global.WebKitBlobBuilder - || global.MSBlobBuilder - || global.MozBlobBuilder; - -/** - * Check if Blob constructor is supported - */ - -var blobSupported = (function() { - try { - var a = new Blob(['hi']); - return a.size === 2; - } catch(e) { - return false; - } -})(); - -/** - * Check if Blob constructor supports ArrayBufferViews - * Fails in Safari 6, so we need to map to ArrayBuffers there. - */ - -var blobSupportsArrayBufferView = blobSupported && (function() { - try { - var b = new Blob([new Uint8Array([1,2])]); - return b.size === 2; - } catch(e) { - return false; - } -})(); - -/** - * Check if BlobBuilder is supported - */ - -var blobBuilderSupported = BlobBuilder - && BlobBuilder.prototype.append - && BlobBuilder.prototype.getBlob; - -/** - * Helper function that maps ArrayBufferViews to ArrayBuffers - * Used by BlobBuilder constructor and old browsers that didn't - * support it in the Blob constructor. - */ - -function mapArrayBufferViews(ary) { - for (var i = 0; i < ary.length; i++) { - var chunk = ary[i]; - if (chunk.buffer instanceof ArrayBuffer) { - var buf = chunk.buffer; - - // if this is a subarray, make a copy so we only - // include the subarray region from the underlying buffer - if (chunk.byteLength !== buf.byteLength) { - var copy = new Uint8Array(chunk.byteLength); - copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength)); - buf = copy.buffer; - } - - ary[i] = buf; - } - } -} - -function BlobBuilderConstructor(ary, options) { - options = options || {}; - - var bb = new BlobBuilder(); - mapArrayBufferViews(ary); - - for (var i = 0; i < ary.length; i++) { - bb.append(ary[i]); - } - - return (options.type) ? bb.getBlob(options.type) : bb.getBlob(); -}; - -function BlobConstructor(ary, options) { - mapArrayBufferViews(ary); - return new Blob(ary, options || {}); -}; - -module.exports = (function() { - if (blobSupported) { - return blobSupportsArrayBufferView ? global.Blob : BlobConstructor; - } else if (blobBuilderSupported) { - return BlobBuilderConstructor; - } else { - return undefined; - } -})(); diff --git a/web/node_modules/blob/package.json b/web/node_modules/blob/package.json deleted file mode 100644 index 31306aa..0000000 --- a/web/node_modules/blob/package.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "_args": [ - [ - "blob@0.0.4", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "blob@0.0.4", - "_id": "blob@0.0.4", - "_inBundle": false, - "_integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", - "_location": "/blob", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "blob@0.0.4", - "name": "blob", - "escapedName": "blob", - "rawSpec": "0.0.4", - "saveSpec": null, - "fetchSpec": "0.0.4" - }, - "_requiredBy": [ - "/engine.io-parser" - ], - "_resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", - "_spec": "0.0.4", - "_where": "/home/treharne/Documents/web/cdt-py", - "bugs": { - "url": "https://github.com/rase-/blob/issues" - }, - "dependencies": {}, - "description": "Abstracts out Blob and uses BlobBulder in cases where it is supported with any vendor prefix.", - "devDependencies": { - "browserify": "3.30.1", - "expect.js": "0.2.0", - "mocha": "1.17.1", - "zuul": "1.5.4" - }, - "homepage": "https://github.com/rase-/blob", - "name": "blob", - "repository": { - "type": "git", - "url": "git+ssh://git@github.com/rase-/blob.git" - }, - "scripts": { - "test": "make test" - }, - "version": "0.0.4" -} diff --git a/web/node_modules/blob/test/index.js b/web/node_modules/blob/test/index.js deleted file mode 100644 index df9303f..0000000 --- a/web/node_modules/blob/test/index.js +++ /dev/null @@ -1,94 +0,0 @@ -var Blob = require('../'); -var expect = require('expect.js'); - -describe('blob', function() { - if (!Blob) { - it('should not have a blob or a blob builder in the global namespace, or blob should not be a constructor function if the module exports false', function() { - try { - var ab = (new Uint8Array(5)).buffer; - global.Blob([ab]); - expect().fail('Blob shouldn\'t be constructable'); - } catch (e) {} - - var BlobBuilder = global.BlobBuilder - || global.WebKitBlobBuilder - || global.MSBlobBuilder - || global.MozBlobBuilder; - expect(BlobBuilder).to.be(undefined); - }); - } else { - it('should encode a proper sized blob when given a string argument', function() { - var b = new Blob(['hi']); - expect(b.size).to.be(2); - }); - - it('should encode a blob with proper size when given two strings as arguments', function() { - var b = new Blob(['hi', 'hello']); - expect(b.size).to.be(7); - }); - - it('should encode arraybuffers with right content', function(done) { - var ary = new Uint8Array(5); - for (var i = 0; i < 5; i++) ary[i] = i; - var b = new Blob([ary.buffer]); - var fr = new FileReader(); - fr.onload = function() { - var newAry = new Uint8Array(this.result); - for (var i = 0; i < 5; i++) expect(newAry[i]).to.be(i); - done(); - }; - fr.readAsArrayBuffer(b); - }); - - it('should encode typed arrays with right content', function(done) { - var ary = new Uint8Array(5); - for (var i = 0; i < 5; i++) ary[i] = i; - var b = new Blob([ary]); - var fr = new FileReader(); - fr.onload = function() { - var newAry = new Uint8Array(this.result); - for (var i = 0; i < 5; i++) expect(newAry[i]).to.be(i); - done(); - }; - fr.readAsArrayBuffer(b); - }); - - it('should encode sliced typed arrays with right content', function(done) { - var ary = new Uint8Array(5); - for (var i = 0; i < 5; i++) ary[i] = i; - var b = new Blob([ary.subarray(2)]); - var fr = new FileReader(); - fr.onload = function() { - var newAry = new Uint8Array(this.result); - for (var i = 0; i < 3; i++) expect(newAry[i]).to.be(i + 2); - done(); - }; - fr.readAsArrayBuffer(b); - }); - - it('should encode with blobs', function(done) { - var ary = new Uint8Array(5); - for (var i = 0; i < 5; i++) ary[i] = i; - var b = new Blob([new Blob([ary.buffer])]); - var fr = new FileReader(); - fr.onload = function() { - var newAry = new Uint8Array(this.result); - for (var i = 0; i < 5; i++) expect(newAry[i]).to.be(i); - done(); - }; - fr.readAsArrayBuffer(b); - }); - - it('should enode mixed contents to right size', function() { - var ary = new Uint8Array(5); - for (var i = 0; i < 5; i++) ary[i] = i; - var b = new Blob([ary.buffer, 'hello']); - expect(b.size).to.be(10); - }); - - it('should accept mime type', function() { - var b = new Blob(['hi', 'hello'], { type: 'text/html' }); - expect(b.type).to.be('text/html'); - }); - } -}); diff --git a/web/node_modules/block-stream/LICENCE b/web/node_modules/block-stream/LICENCE deleted file mode 100644 index 74489e2..0000000 --- a/web/node_modules/block-stream/LICENCE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) Isaac Z. Schlueter -All rights reserved. - -The BSD License - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS -``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/web/node_modules/block-stream/LICENSE b/web/node_modules/block-stream/LICENSE deleted file mode 100644 index 19129e3..0000000 --- a/web/node_modules/block-stream/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/web/node_modules/block-stream/README.md b/web/node_modules/block-stream/README.md deleted file mode 100644 index c16e9c4..0000000 --- a/web/node_modules/block-stream/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# block-stream - -A stream of blocks. - -Write data into it, and it'll output data in buffer blocks the size you -specify, padding with zeroes if necessary. - -```javascript -var block = new BlockStream(512) -fs.createReadStream("some-file").pipe(block) -block.pipe(fs.createWriteStream("block-file")) -``` - -When `.end()` or `.flush()` is called, it'll pad the block with zeroes. diff --git a/web/node_modules/block-stream/block-stream.js b/web/node_modules/block-stream/block-stream.js deleted file mode 100644 index 008de03..0000000 --- a/web/node_modules/block-stream/block-stream.js +++ /dev/null @@ -1,209 +0,0 @@ -// write data to it, and it'll emit data in 512 byte blocks. -// if you .end() or .flush(), it'll emit whatever it's got, -// padded with nulls to 512 bytes. - -module.exports = BlockStream - -var Stream = require("stream").Stream - , inherits = require("inherits") - , assert = require("assert").ok - , debug = process.env.DEBUG ? console.error : function () {} - -function BlockStream (size, opt) { - this.writable = this.readable = true - this._opt = opt || {} - this._chunkSize = size || 512 - this._offset = 0 - this._buffer = [] - this._bufferLength = 0 - if (this._opt.nopad) this._zeroes = false - else { - this._zeroes = new Buffer(this._chunkSize) - for (var i = 0; i < this._chunkSize; i ++) { - this._zeroes[i] = 0 - } - } -} - -inherits(BlockStream, Stream) - -BlockStream.prototype.write = function (c) { - // debug(" BS write", c) - if (this._ended) throw new Error("BlockStream: write after end") - if (c && !Buffer.isBuffer(c)) c = new Buffer(c + "") - if (c.length) { - this._buffer.push(c) - this._bufferLength += c.length - } - // debug("pushed onto buffer", this._bufferLength) - if (this._bufferLength >= this._chunkSize) { - if (this._paused) { - // debug(" BS paused, return false, need drain") - this._needDrain = true - return false - } - this._emitChunk() - } - return true -} - -BlockStream.prototype.pause = function () { - // debug(" BS pausing") - this._paused = true -} - -BlockStream.prototype.resume = function () { - // debug(" BS resume") - this._paused = false - return this._emitChunk() -} - -BlockStream.prototype.end = function (chunk) { - // debug("end", chunk) - if (typeof chunk === "function") cb = chunk, chunk = null - if (chunk) this.write(chunk) - this._ended = true - this.flush() -} - -BlockStream.prototype.flush = function () { - this._emitChunk(true) -} - -BlockStream.prototype._emitChunk = function (flush) { - // debug("emitChunk flush=%j emitting=%j paused=%j", flush, this._emitting, this._paused) - - // emit a chunk - if (flush && this._zeroes) { - // debug(" BS push zeroes", this._bufferLength) - // push a chunk of zeroes - var padBytes = (this._bufferLength % this._chunkSize) - if (padBytes !== 0) padBytes = this._chunkSize - padBytes - if (padBytes > 0) { - // debug("padBytes", padBytes, this._zeroes.slice(0, padBytes)) - this._buffer.push(this._zeroes.slice(0, padBytes)) - this._bufferLength += padBytes - // debug(this._buffer[this._buffer.length - 1].length, this._bufferLength) - } - } - - if (this._emitting || this._paused) return - this._emitting = true - - // debug(" BS entering loops") - var bufferIndex = 0 - while (this._bufferLength >= this._chunkSize && - (flush || !this._paused)) { - // debug(" BS data emission loop", this._bufferLength) - - var out - , outOffset = 0 - , outHas = this._chunkSize - - while (outHas > 0 && (flush || !this._paused) ) { - // debug(" BS data inner emit loop", this._bufferLength) - var cur = this._buffer[bufferIndex] - , curHas = cur.length - this._offset - // debug("cur=", cur) - // debug("curHas=%j", curHas) - // If it's not big enough to fill the whole thing, then we'll need - // to copy multiple buffers into one. However, if it is big enough, - // then just slice out the part we want, to save unnecessary copying. - // Also, need to copy if we've already done some copying, since buffers - // can't be joined like cons strings. - if (out || curHas < outHas) { - out = out || new Buffer(this._chunkSize) - cur.copy(out, outOffset, - this._offset, this._offset + Math.min(curHas, outHas)) - } else if (cur.length === outHas && this._offset === 0) { - // shortcut -- cur is exactly long enough, and no offset. - out = cur - } else { - // slice out the piece of cur that we need. - out = cur.slice(this._offset, this._offset + outHas) - } - - if (curHas > outHas) { - // means that the current buffer couldn't be completely output - // update this._offset to reflect how much WAS written - this._offset += outHas - outHas = 0 - } else { - // output the entire current chunk. - // toss it away - outHas -= curHas - outOffset += curHas - bufferIndex ++ - this._offset = 0 - } - } - - this._bufferLength -= this._chunkSize - assert(out.length === this._chunkSize) - // debug("emitting data", out) - // debug(" BS emitting, paused=%j", this._paused, this._bufferLength) - this.emit("data", out) - out = null - } - // debug(" BS out of loops", this._bufferLength) - - // whatever is left, it's not enough to fill up a block, or we're paused - this._buffer = this._buffer.slice(bufferIndex) - if (this._paused) { - // debug(" BS paused, leaving", this._bufferLength) - this._needsDrain = true - this._emitting = false - return - } - - // if flushing, and not using null-padding, then need to emit the last - // chunk(s) sitting in the queue. We know that it's not enough to - // fill up a whole block, because otherwise it would have been emitted - // above, but there may be some offset. - var l = this._buffer.length - if (flush && !this._zeroes && l) { - if (l === 1) { - if (this._offset) { - this.emit("data", this._buffer[0].slice(this._offset)) - } else { - this.emit("data", this._buffer[0]) - } - } else { - var outHas = this._bufferLength - , out = new Buffer(outHas) - , outOffset = 0 - for (var i = 0; i < l; i ++) { - var cur = this._buffer[i] - , curHas = cur.length - this._offset - cur.copy(out, outOffset, this._offset) - this._offset = 0 - outOffset += curHas - this._bufferLength -= curHas - } - this.emit("data", out) - } - // truncate - this._buffer.length = 0 - this._bufferLength = 0 - this._offset = 0 - } - - // now either drained or ended - // debug("either draining, or ended", this._bufferLength, this._ended) - // means that we've flushed out all that we can so far. - if (this._needDrain) { - // debug("emitting drain", this._bufferLength) - this._needDrain = false - this.emit("drain") - } - - if ((this._bufferLength === 0) && this._ended && !this._endEmitted) { - // debug("emitting end", this._bufferLength) - this._endEmitted = true - this.emit("end") - } - - this._emitting = false - - // debug(" BS no longer emitting", flush, this._paused, this._emitting, this._bufferLength, this._chunkSize) -} diff --git a/web/node_modules/block-stream/package.json b/web/node_modules/block-stream/package.json deleted file mode 100644 index 75712e5..0000000 --- a/web/node_modules/block-stream/package.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "_args": [ - [ - "block-stream@0.0.9", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "block-stream@0.0.9", - "_id": "block-stream@0.0.9", - "_inBundle": false, - "_integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "_location": "/block-stream", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "block-stream@0.0.9", - "name": "block-stream", - "escapedName": "block-stream", - "rawSpec": "0.0.9", - "saveSpec": null, - "fetchSpec": "0.0.9" - }, - "_requiredBy": [ - "/tar" - ], - "_resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "_spec": "0.0.9", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me", - "url": "http://blog.izs.me/" - }, - "bugs": { - "url": "https://github.com/isaacs/block-stream/issues" - }, - "dependencies": { - "inherits": "~2.0.0" - }, - "description": "a stream of blocks", - "devDependencies": { - "tap": "^5.7.1" - }, - "engines": { - "node": "0.4 || >=0.5.8" - }, - "files": [ - "block-stream.js" - ], - "homepage": "https://github.com/isaacs/block-stream#readme", - "license": "ISC", - "main": "block-stream.js", - "name": "block-stream", - "repository": { - "type": "git", - "url": "git://github.com/isaacs/block-stream.git" - }, - "scripts": { - "test": "tap test/*.js --cov" - }, - "version": "0.0.9" -} diff --git a/web/node_modules/boom/.npmignore b/web/node_modules/boom/.npmignore deleted file mode 100644 index 77ba16c..0000000 --- a/web/node_modules/boom/.npmignore +++ /dev/null @@ -1,18 +0,0 @@ -.idea -*.iml -npm-debug.log -dump.rdb -node_modules -results.tap -results.xml -npm-shrinkwrap.json -config.json -.DS_Store -*/.DS_Store -*/*/.DS_Store -._* -*/._* -*/*/._* -coverage.* -lib-cov - diff --git a/web/node_modules/boom/.travis.yml b/web/node_modules/boom/.travis.yml deleted file mode 100755 index dd1b24f..0000000 --- a/web/node_modules/boom/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: node_js - -node_js: - - 0.10 - - 4.0 - -sudo: false - diff --git a/web/node_modules/boom/CONTRIBUTING.md b/web/node_modules/boom/CONTRIBUTING.md deleted file mode 100644 index 8928361..0000000 --- a/web/node_modules/boom/CONTRIBUTING.md +++ /dev/null @@ -1 +0,0 @@ -Please view our [hapijs contributing guide](https://github.com/hapijs/hapi/blob/master/CONTRIBUTING.md). diff --git a/web/node_modules/boom/LICENSE b/web/node_modules/boom/LICENSE deleted file mode 100755 index 3946889..0000000 --- a/web/node_modules/boom/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2012-2014, Walmart and other contributors. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The names of any contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - * * * - -The complete list of contributors can be found at: https://github.com/hapijs/boom/graphs/contributors \ No newline at end of file diff --git a/web/node_modules/boom/README.md b/web/node_modules/boom/README.md deleted file mode 100755 index cbd91c9..0000000 --- a/web/node_modules/boom/README.md +++ /dev/null @@ -1,652 +0,0 @@ -![boom Logo](https://raw.github.com/hapijs/boom/master/images/boom.png) - -HTTP-friendly error objects - -[![Build Status](https://secure.travis-ci.org/hapijs/boom.png)](http://travis-ci.org/hapijs/boom) -[![Current Version](https://img.shields.io/npm/v/boom.svg)](https://www.npmjs.com/package/boom) - -Lead Maintainer: [Adam Bretz](https://github.com/arb) - -**boom** provides a set of utilities for returning HTTP errors. Each utility returns a `Boom` error response -object (instance of `Error`) which includes the following properties: -- `isBoom` - if `true`, indicates this is a `Boom` object instance. -- `isServer` - convenience bool indicating status code >= 500. -- `message` - the error message. -- `output` - the formatted response. Can be directly manipulated after object construction to return a custom - error response. Allowed root keys: - - `statusCode` - the HTTP status code (typically 4xx or 5xx). - - `headers` - an object containing any HTTP headers where each key is a header name and value is the header content. - - `payload` - the formatted object used as the response payload (stringified). Can be directly manipulated but any - changes will be lost - if `reformat()` is called. Any content allowed and by default includes the following content: - - `statusCode` - the HTTP status code, derived from `error.output.statusCode`. - - `error` - the HTTP status message (e.g. 'Bad Request', 'Internal Server Error') derived from `statusCode`. - - `message` - the error message derived from `error.message`. -- inherited `Error` properties. - -The `Boom` object also supports the following method: -- `reformat()` - rebuilds `error.output` using the other object properties. - -## Overview - -- Helper methods - - [`wrap(error, [statusCode], [message])`](#wraperror-statuscode-message) - - [`create(statusCode, [message], [data])`](#createstatuscode-message-data) -- HTTP 4xx Errors - - 400: [`Boom.badRequest([message], [data])`](#boombadrequestmessage-data) - - 401: [`Boom.unauthorized([message], [scheme], [attributes])`](#boomunauthorizedmessage-scheme-attributes) - - 403: [`Boom.forbidden([message], [data])`](#boomforbiddenmessage-data) - - 404: [`Boom.notFound([message], [data])`](#boomnotfoundmessage-data) - - 405: [`Boom.methodNotAllowed([message], [data])`](#boommethodnotallowedmessage-data) - - 406: [`Boom.notAcceptable([message], [data])`](#boomnotacceptablemessage-data) - - 407: [`Boom.proxyAuthRequired([message], [data])`](#boomproxyauthrequiredmessage-data) - - 408: [`Boom.clientTimeout([message], [data])`](#boomclienttimeoutmessage-data) - - 409: [`Boom.conflict([message], [data])`](#boomconflictmessage-data) - - 410: [`Boom.resourceGone([message], [data])`](#boomresourcegonemessage-data) - - 411: [`Boom.lengthRequired([message], [data])`](#boomlengthrequiredmessage-data) - - 412: [`Boom.preconditionFailed([message], [data])`](#boompreconditionfailedmessage-data) - - 413: [`Boom.entityTooLarge([message], [data])`](#boomentitytoolargemessage-data) - - 414: [`Boom.uriTooLong([message], [data])`](#boomuritoolongmessage-data) - - 415: [`Boom.unsupportedMediaType([message], [data])`](#boomunsupportedmediatypemessage-data) - - 416: [`Boom.rangeNotSatisfiable([message], [data])`](#boomrangenotsatisfiablemessage-data) - - 417: [`Boom.expectationFailed([message], [data])`](#boomexpectationfailedmessage-data) - - 422: [`Boom.badData([message], [data])`](#boombaddatamessage-data) - - 428: [`Boom.preconditionRequired([message], [data])`](#boompreconditionrequiredmessage-data) - - 429: [`Boom.tooManyRequests([message], [data])`](#boomtoomanyrequestsmessage-data) -- HTTP 5xx Errors - - 500: [`Boom.badImplementation([message], [data])`](#boombadimplementationmessage-data) - - 501: [`Boom.notImplemented([message], [data])`](#boomnotimplementedmessage-data) - - 502: [`Boom.badGateway([message], [data])`](#boombadgatewaymessage-data) - - 503: [`Boom.serverTimeout([message], [data])`](#boomservertimeoutmessage-data) - - 504: [`Boom.gatewayTimeout([message], [data])`](#boomgatewaytimeoutmessage-data) -- [FAQ](#faq) - - -## Helper Methods - -### `wrap(error, [statusCode], [message])` - -Decorates an error with the **boom** properties where: -- `error` - the error object to wrap. If `error` is already a **boom** object, returns back the same object. -- `statusCode` - optional HTTP status code. Defaults to `500`. -- `message` - optional message string. If the error already has a message, it adds the message as a prefix. - Defaults to no message. - -```js -var error = new Error('Unexpected input'); -Boom.wrap(error, 400); -``` - -### `create(statusCode, [message], [data])` - -Generates an `Error` object with the **boom** decorations where: -- `statusCode` - an HTTP error code number. Must be greater or equal 400. -- `message` - optional message string. -- `data` - additional error data set to `error.data` property. - -```js -var error = Boom.create(400, 'Bad request', { timestamp: Date.now() }); -``` - -## HTTP 4xx Errors - -### `Boom.badRequest([message], [data])` - -Returns a 400 Bad Request error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.badRequest('invalid query'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 400, - "error": "Bad Request", - "message": "invalid query" -} -``` - -### `Boom.unauthorized([message], [scheme], [attributes])` - -Returns a 401 Unauthorized error where: -- `message` - optional message. -- `scheme` can be one of the following: - - an authentication scheme name - - an array of string values. These values will be separated by ', ' and set to the 'WWW-Authenticate' header. -- `attributes` - an object of values to use while setting the 'WWW-Authenticate' header. This value is only used - when `schema` is a string, otherwise it is ignored. Every key/value pair will be included in the - 'WWW-Authenticate' in the format of 'key="value"' as well as in the response payload under the `attributes` key. - `null` and `undefined` will be replaced with an empty string. If `attributes` is set, `message` will be used as - the 'error' segment of the 'WWW-Authenticate' header. If `message` is unset, the 'error' segment of the header - will not be present and `isMissing` will be true on the error object. - -If either `scheme` or `attributes` are set, the resultant `Boom` object will have the 'WWW-Authenticate' header set for the response. - -```js -Boom.unauthorized('invalid password'); -``` - -Generates the following response: - -```json -"payload": { - "statusCode": 401, - "error": "Unauthorized", - "message": "invalid password" -}, -"headers" {} -``` - -```js -Boom.unauthorized('invalid password', 'sample'); -``` - -Generates the following response: - -```json -"payload": { - "statusCode": 401, - "error": "Unauthorized", - "message": "invalid password", - "attributes": { - "error": "invalid password" - } -}, -"headers" { - "WWW-Authenticate": "sample error=\"invalid password\"" -} -``` - -```js -Boom.unauthorized('invalid password', 'sample', { ttl: 0, cache: null, foo: 'bar' }); -``` - -Generates the following response: - -```json -"payload": { - "statusCode": 401, - "error": "Unauthorized", - "message": "invalid password", - "attributes": { - "error": "invalid password", - "ttl": 0, - "cache": "", - "foo": "bar" - } -}, -"headers" { - "WWW-Authenticate": "sample ttl=\"0\", cache=\"\", foo=\"bar\", error=\"invalid password\"" -} -``` - -### `Boom.forbidden([message], [data])` - -Returns a 403 Forbidden error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.forbidden('try again some time'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 403, - "error": "Forbidden", - "message": "try again some time" -} -``` - -### `Boom.notFound([message], [data])` - -Returns a 404 Not Found error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.notFound('missing'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 404, - "error": "Not Found", - "message": "missing" -} -``` - -### `Boom.methodNotAllowed([message], [data])` - -Returns a 405 Method Not Allowed error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.methodNotAllowed('that method is not allowed'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 405, - "error": "Method Not Allowed", - "message": "that method is not allowed" -} -``` - -### `Boom.notAcceptable([message], [data])` - -Returns a 406 Not Acceptable error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.notAcceptable('unacceptable'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 406, - "error": "Not Acceptable", - "message": "unacceptable" -} -``` - -### `Boom.proxyAuthRequired([message], [data])` - -Returns a 407 Proxy Authentication Required error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.proxyAuthRequired('auth missing'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 407, - "error": "Proxy Authentication Required", - "message": "auth missing" -} -``` - -### `Boom.clientTimeout([message], [data])` - -Returns a 408 Request Time-out error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.clientTimeout('timed out'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 408, - "error": "Request Time-out", - "message": "timed out" -} -``` - -### `Boom.conflict([message], [data])` - -Returns a 409 Conflict error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.conflict('there was a conflict'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 409, - "error": "Conflict", - "message": "there was a conflict" -} -``` - -### `Boom.resourceGone([message], [data])` - -Returns a 410 Gone error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.resourceGone('it is gone'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 410, - "error": "Gone", - "message": "it is gone" -} -``` - -### `Boom.lengthRequired([message], [data])` - -Returns a 411 Length Required error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.lengthRequired('length needed'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 411, - "error": "Length Required", - "message": "length needed" -} -``` - -### `Boom.preconditionFailed([message], [data])` - -Returns a 412 Precondition Failed error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.preconditionFailed(); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 412, - "error": "Precondition Failed" -} -``` - -### `Boom.entityTooLarge([message], [data])` - -Returns a 413 Request Entity Too Large error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.entityTooLarge('too big'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 413, - "error": "Request Entity Too Large", - "message": "too big" -} -``` - -### `Boom.uriTooLong([message], [data])` - -Returns a 414 Request-URI Too Large error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.uriTooLong('uri is too long'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 414, - "error": "Request-URI Too Large", - "message": "uri is too long" -} -``` - -### `Boom.unsupportedMediaType([message], [data])` - -Returns a 415 Unsupported Media Type error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.unsupportedMediaType('that media is not supported'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 415, - "error": "Unsupported Media Type", - "message": "that media is not supported" -} -``` - -### `Boom.rangeNotSatisfiable([message], [data])` - -Returns a 416 Requested Range Not Satisfiable error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.rangeNotSatisfiable(); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 416, - "error": "Requested Range Not Satisfiable" -} -``` - -### `Boom.expectationFailed([message], [data])` - -Returns a 417 Expectation Failed error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.expectationFailed('expected this to work'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 417, - "error": "Expectation Failed", - "message": "expected this to work" -} -``` - -### `Boom.badData([message], [data])` - -Returns a 422 Unprocessable Entity error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.badData('your data is bad and you should feel bad'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 422, - "error": "Unprocessable Entity", - "message": "your data is bad and you should feel bad" -} -``` - -### `Boom.preconditionRequired([message], [data])` - -Returns a 428 Precondition Required error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.preconditionRequired('you must supply an If-Match header'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 428, - "error": "Precondition Required", - "message": "you must supply an If-Match header" -} -``` - -### `Boom.tooManyRequests([message], [data])` - -Returns a 429 Too Many Requests error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.tooManyRequests('you have exceeded your request limit'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 429, - "error": "Too Many Requests", - "message": "you have exceeded your request limit" -} -``` - -## HTTP 5xx Errors - -All 500 errors hide your message from the end user. Your message is recorded in the server log. - -### `Boom.badImplementation([message], [data])` - -Returns a 500 Internal Server Error error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.badImplementation('terrible implementation'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 500, - "error": "Internal Server Error", - "message": "An internal server error occurred" -} -``` - -### `Boom.notImplemented([message], [data])` - -Returns a 501 Not Implemented error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.notImplemented('method not implemented'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 501, - "error": "Not Implemented", - "message": "method not implemented" -} -``` - -### `Boom.badGateway([message], [data])` - -Returns a 502 Bad Gateway error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.badGateway('that is a bad gateway'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 502, - "error": "Bad Gateway", - "message": "that is a bad gateway" -} -``` - -### `Boom.serverTimeout([message], [data])` - -Returns a 503 Service Unavailable error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.serverTimeout('unavailable'); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 503, - "error": "Service Unavailable", - "message": "unavailable" -} -``` - -### `Boom.gatewayTimeout([message], [data])` - -Returns a 504 Gateway Time-out error where: -- `message` - optional message. -- `data` - optional additional error data. - -```js -Boom.gatewayTimeout(); -``` - -Generates the following response payload: - -```json -{ - "statusCode": 504, - "error": "Gateway Time-out" -} -``` - -## F.A.Q. - -###### How do I include extra information in my responses? `output.payload` is missing `data`, what gives? - -There is a reason the values passed back in the response payloads are pretty locked down. It's mostly for security and to not leak any important information back to the client. This means you will need to put in a little more effort to include extra information about your custom error. Check out the ["Error transformation"](https://github.com/hapijs/hapi/blob/master/API.md#error-transformation) section in the hapi documentation. diff --git a/web/node_modules/boom/images/boom.png b/web/node_modules/boom/images/boom.png deleted file mode 100755 index 373bc13..0000000 Binary files a/web/node_modules/boom/images/boom.png and /dev/null differ diff --git a/web/node_modules/boom/lib/index.js b/web/node_modules/boom/lib/index.js deleted file mode 100755 index 6bdea69..0000000 --- a/web/node_modules/boom/lib/index.js +++ /dev/null @@ -1,318 +0,0 @@ -// Load modules - -var Http = require('http'); -var Hoek = require('hoek'); - - -// Declare internals - -var internals = {}; - -exports.wrap = function (error, statusCode, message) { - - Hoek.assert(error instanceof Error, 'Cannot wrap non-Error object'); - return (error.isBoom ? error : internals.initialize(error, statusCode || 500, message)); -}; - - -exports.create = function (statusCode, message, data) { - - return internals.create(statusCode, message, data, exports.create); -}; - -internals.create = function (statusCode, message, data, ctor) { - - var error = new Error(message ? message : undefined); // Avoids settings null message - Error.captureStackTrace(error, ctor); // Filter the stack to our external API - error.data = data || null; - internals.initialize(error, statusCode); - return error; -}; - -internals.initialize = function (error, statusCode, message) { - - var numberCode = parseInt(statusCode, 10); - Hoek.assert(!isNaN(numberCode) && numberCode >= 400, 'First argument must be a number (400+):', statusCode); - - error.isBoom = true; - error.isServer = numberCode >= 500; - - if (!error.hasOwnProperty('data')) { - error.data = null; - } - - error.output = { - statusCode: numberCode, - payload: {}, - headers: {} - }; - - error.reformat = internals.reformat; - error.reformat(); - - if (!message && - !error.message) { - - message = error.output.payload.error; - } - - if (message) { - error.message = (message + (error.message ? ': ' + error.message : '')); - } - - return error; -}; - - -internals.reformat = function () { - - this.output.payload.statusCode = this.output.statusCode; - this.output.payload.error = Http.STATUS_CODES[this.output.statusCode] || 'Unknown'; - - if (this.output.statusCode === 500) { - this.output.payload.message = 'An internal server error occurred'; // Hide actual error from user - } - else if (this.message) { - this.output.payload.message = this.message; - } -}; - - -// 4xx Client Errors - -exports.badRequest = function (message, data) { - - return internals.create(400, message, data, exports.badRequest); -}; - - -exports.unauthorized = function (message, scheme, attributes) { // Or function (message, wwwAuthenticate[]) - - var err = internals.create(401, message, undefined, exports.unauthorized); - - if (!scheme) { - return err; - } - - var wwwAuthenticate = ''; - var i = 0; - var il = 0; - - if (typeof scheme === 'string') { - - // function (message, scheme, attributes) - - wwwAuthenticate = scheme; - - if (attributes || message) { - err.output.payload.attributes = {}; - } - - if (attributes) { - var names = Object.keys(attributes); - for (i = 0, il = names.length; i < il; ++i) { - var name = names[i]; - if (i) { - wwwAuthenticate += ','; - } - - var value = attributes[name]; - if (value === null || - value === undefined) { // Value can be zero - - value = ''; - } - wwwAuthenticate += ' ' + name + '="' + Hoek.escapeHeaderAttribute(value.toString()) + '"'; - err.output.payload.attributes[name] = value; - } - } - - if (message) { - if (attributes) { - wwwAuthenticate += ','; - } - wwwAuthenticate += ' error="' + Hoek.escapeHeaderAttribute(message) + '"'; - err.output.payload.attributes.error = message; - } - else { - err.isMissing = true; - } - } - else { - - // function (message, wwwAuthenticate[]) - - var wwwArray = scheme; - for (i = 0, il = wwwArray.length; i < il; ++i) { - if (i) { - wwwAuthenticate += ', '; - } - - wwwAuthenticate += wwwArray[i]; - } - } - - err.output.headers['WWW-Authenticate'] = wwwAuthenticate; - - return err; -}; - - -exports.forbidden = function (message, data) { - - return internals.create(403, message, data, exports.forbidden); -}; - - -exports.notFound = function (message, data) { - - return internals.create(404, message, data, exports.notFound); -}; - - -exports.methodNotAllowed = function (message, data) { - - return internals.create(405, message, data, exports.methodNotAllowed); -}; - - -exports.notAcceptable = function (message, data) { - - return internals.create(406, message, data, exports.notAcceptable); -}; - - -exports.proxyAuthRequired = function (message, data) { - - return internals.create(407, message, data, exports.proxyAuthRequired); -}; - - -exports.clientTimeout = function (message, data) { - - return internals.create(408, message, data, exports.clientTimeout); -}; - - -exports.conflict = function (message, data) { - - return internals.create(409, message, data, exports.conflict); -}; - - -exports.resourceGone = function (message, data) { - - return internals.create(410, message, data, exports.resourceGone); -}; - - -exports.lengthRequired = function (message, data) { - - return internals.create(411, message, data, exports.lengthRequired); -}; - - -exports.preconditionFailed = function (message, data) { - - return internals.create(412, message, data, exports.preconditionFailed); -}; - - -exports.entityTooLarge = function (message, data) { - - return internals.create(413, message, data, exports.entityTooLarge); -}; - - -exports.uriTooLong = function (message, data) { - - return internals.create(414, message, data, exports.uriTooLong); -}; - - -exports.unsupportedMediaType = function (message, data) { - - return internals.create(415, message, data, exports.unsupportedMediaType); -}; - - -exports.rangeNotSatisfiable = function (message, data) { - - return internals.create(416, message, data, exports.rangeNotSatisfiable); -}; - - -exports.expectationFailed = function (message, data) { - - return internals.create(417, message, data, exports.expectationFailed); -}; - -exports.badData = function (message, data) { - - return internals.create(422, message, data, exports.badData); -}; - - -exports.preconditionRequired = function (message, data) { - - return internals.create(428, message, data, exports.preconditionRequired); -}; - - -exports.tooManyRequests = function (message, data) { - - return internals.create(429, message, data, exports.tooManyRequests); -}; - - -// 5xx Server Errors - -exports.internal = function (message, data, statusCode) { - - return internals.serverError(message, data, statusCode, exports.internal); -}; - -internals.serverError = function (message, data, statusCode, ctor) { - - var error; - if (data instanceof Error) { - error = exports.wrap(data, statusCode, message); - } else { - error = internals.create(statusCode || 500, message, undefined, ctor); - error.data = data; - } - - return error; -}; - - -exports.notImplemented = function (message, data) { - - return internals.serverError(message, data, 501, exports.notImplemented); -}; - - -exports.badGateway = function (message, data) { - - return internals.serverError(message, data, 502, exports.badGateway); -}; - - -exports.serverTimeout = function (message, data) { - - return internals.serverError(message, data, 503, exports.serverTimeout); -}; - - -exports.gatewayTimeout = function (message, data) { - - return internals.serverError(message, data, 504, exports.gatewayTimeout); -}; - - -exports.badImplementation = function (message, data) { - - var err = internals.serverError(message, data, 500, exports.badImplementation); - err.isDeveloperError = true; - return err; -}; diff --git a/web/node_modules/boom/package.json b/web/node_modules/boom/package.json deleted file mode 100644 index 01832ce..0000000 --- a/web/node_modules/boom/package.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "_args": [ - [ - "boom@2.10.1", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "boom@2.10.1", - "_id": "boom@2.10.1", - "_inBundle": false, - "_integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "_location": "/boom", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "boom@2.10.1", - "name": "boom", - "escapedName": "boom", - "rawSpec": "2.10.1", - "saveSpec": null, - "fetchSpec": "2.10.1" - }, - "_requiredBy": [ - "/cryptiles", - "/hawk" - ], - "_resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "_spec": "2.10.1", - "_where": "/home/treharne/Documents/web/cdt-py", - "bugs": { - "url": "https://github.com/hapijs/boom/issues" - }, - "dependencies": { - "hoek": "2.x.x" - }, - "description": "HTTP-friendly error objects", - "devDependencies": { - "code": "1.x.x", - "lab": "7.x.x" - }, - "engines": { - "node": ">=0.10.40" - }, - "homepage": "https://github.com/hapijs/boom#readme", - "keywords": [ - "error", - "http" - ], - "license": "BSD-3-Clause", - "main": "lib/index.js", - "name": "boom", - "repository": { - "type": "git", - "url": "git://github.com/hapijs/boom.git" - }, - "scripts": { - "test": "lab -a code -t 100 -L", - "test-cov-html": "lab -a code -r html -o coverage.html -L" - }, - "version": "2.10.1" -} diff --git a/web/node_modules/boom/test/index.js b/web/node_modules/boom/test/index.js deleted file mode 100755 index 79a59e9..0000000 --- a/web/node_modules/boom/test/index.js +++ /dev/null @@ -1,654 +0,0 @@ -// Load modules - -var Code = require('code'); -var Boom = require('../lib'); -var Lab = require('lab'); - - -// Declare internals - -var internals = {}; - - -// Test shortcuts - -var lab = exports.lab = Lab.script(); -var describe = lab.describe; -var it = lab.it; -var expect = Code.expect; - - -it('returns the same object when already boom', function (done) { - - var error = Boom.badRequest(); - var wrapped = Boom.wrap(error); - expect(error).to.equal(wrapped); - done(); -}); - -it('returns an error with info when constructed using another error', function (done) { - - var error = new Error('ka-boom'); - error.xyz = 123; - var err = Boom.wrap(error); - expect(err.xyz).to.equal(123); - expect(err.message).to.equal('ka-boom'); - expect(err.output).to.deep.equal({ - statusCode: 500, - payload: { - statusCode: 500, - error: 'Internal Server Error', - message: 'An internal server error occurred' - }, - headers: {} - }); - expect(err.data).to.equal(null); - done(); -}); - -it('does not override data when constructed using another error', function (done) { - - var error = new Error('ka-boom'); - error.data = { useful: 'data' }; - var err = Boom.wrap(error); - expect(err.data).to.equal(error.data); - done(); -}); - -it('sets new message when none exists', function (done) { - - var error = new Error(); - var wrapped = Boom.wrap(error, 400, 'something bad'); - expect(wrapped.message).to.equal('something bad'); - done(); -}); - -it('throws when statusCode is not a number', function (done) { - - expect(function () { - - Boom.create('x'); - }).to.throw('First argument must be a number (400+): x'); - done(); -}); - -it('will cast a number-string to an integer', function (done) { - - var codes = [ - { input: '404', result: 404 }, - { input: '404.1', result: 404 }, - { input: 400, result: 400 }, - { input: 400.123, result: 400 }]; - for (var i = 0, il = codes.length; i < il; ++i) { - var code = codes[i]; - var err = Boom.create(code.input); - expect(err.output.statusCode).to.equal(code.result); - } - - done(); -}); - -it('throws when statusCode is not finite', function (done) { - - expect(function () { - - Boom.create(1 / 0); - }).to.throw('First argument must be a number (400+): null'); - done(); -}); - -it('sets error code to unknown', function (done) { - - var err = Boom.create(999); - expect(err.output.payload.error).to.equal('Unknown'); - done(); -}); - -describe('create()', function () { - - it('does not sets null message', function (done) { - - var error = Boom.unauthorized(null); - expect(error.output.payload.message).to.not.exist(); - expect(error.isServer).to.be.false(); - done(); - }); - - it('sets message and data', function (done) { - - var error = Boom.badRequest('Missing data', { type: 'user' }); - expect(error.data.type).to.equal('user'); - expect(error.output.payload.message).to.equal('Missing data'); - done(); - }); -}); - -describe('isBoom()', function () { - - it('returns true for Boom object', function (done) { - - expect(Boom.badRequest().isBoom).to.equal(true); - done(); - }); - - it('returns false for Error object', function (done) { - - expect((new Error()).isBoom).to.not.exist(); - done(); - }); -}); - -describe('badRequest()', function () { - - it('returns a 400 error statusCode', function (done) { - - var error = Boom.badRequest(); - - expect(error.output.statusCode).to.equal(400); - expect(error.isServer).to.be.false(); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.badRequest('my message').message).to.equal('my message'); - done(); - }); - - it('sets the message to HTTP status if none provided', function (done) { - - expect(Boom.badRequest().message).to.equal('Bad Request'); - done(); - }); -}); - -describe('unauthorized()', function () { - - it('returns a 401 error statusCode', function (done) { - - var err = Boom.unauthorized(); - expect(err.output.statusCode).to.equal(401); - expect(err.output.headers).to.deep.equal({}); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.unauthorized('my message').message).to.equal('my message'); - done(); - }); - - it('returns a WWW-Authenticate header when passed a scheme', function (done) { - - var err = Boom.unauthorized('boom', 'Test'); - expect(err.output.statusCode).to.equal(401); - expect(err.output.headers['WWW-Authenticate']).to.equal('Test error="boom"'); - done(); - }); - - it('returns a WWW-Authenticate header set to the schema array value', function (done) { - - var err = Boom.unauthorized(null, ['Test','one','two']); - expect(err.output.statusCode).to.equal(401); - expect(err.output.headers['WWW-Authenticate']).to.equal('Test, one, two'); - done(); - }); - - it('returns a WWW-Authenticate header when passed a scheme and attributes', function (done) { - - var err = Boom.unauthorized('boom', 'Test', { a: 1, b: 'something', c: null, d: 0 }); - expect(err.output.statusCode).to.equal(401); - expect(err.output.headers['WWW-Authenticate']).to.equal('Test a="1", b="something", c="", d="0", error="boom"'); - expect(err.output.payload.attributes).to.deep.equal({ a: 1, b: 'something', c: '', d: 0, error: 'boom' }); - done(); - }); - - it('returns a WWW-Authenticate header when passed attributes, missing error', function (done) { - - var err = Boom.unauthorized(null, 'Test', { a: 1, b: 'something', c: null, d: 0 }); - expect(err.output.statusCode).to.equal(401); - expect(err.output.headers['WWW-Authenticate']).to.equal('Test a="1", b="something", c="", d="0"'); - expect(err.isMissing).to.equal(true); - done(); - }); - - it('sets the isMissing flag when error message is empty', function (done) { - - var err = Boom.unauthorized('', 'Basic'); - expect(err.isMissing).to.equal(true); - done(); - }); - - it('does not set the isMissing flag when error message is not empty', function (done) { - - var err = Boom.unauthorized('message', 'Basic'); - expect(err.isMissing).to.equal(undefined); - done(); - }); - - it('sets a WWW-Authenticate when passed as an array', function (done) { - - var err = Boom.unauthorized('message', ['Basic', 'Example e="1"', 'Another x="3", y="4"']); - expect(err.output.headers['WWW-Authenticate']).to.equal('Basic, Example e="1", Another x="3", y="4"'); - done(); - }); -}); - - -describe('methodNotAllowed()', function () { - - it('returns a 405 error statusCode', function (done) { - - expect(Boom.methodNotAllowed().output.statusCode).to.equal(405); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.methodNotAllowed('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('notAcceptable()', function () { - - it('returns a 406 error statusCode', function (done) { - - expect(Boom.notAcceptable().output.statusCode).to.equal(406); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.notAcceptable('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('proxyAuthRequired()', function () { - - it('returns a 407 error statusCode', function (done) { - - expect(Boom.proxyAuthRequired().output.statusCode).to.equal(407); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.proxyAuthRequired('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('clientTimeout()', function () { - - it('returns a 408 error statusCode', function (done) { - - expect(Boom.clientTimeout().output.statusCode).to.equal(408); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.clientTimeout('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('conflict()', function () { - - it('returns a 409 error statusCode', function (done) { - - expect(Boom.conflict().output.statusCode).to.equal(409); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.conflict('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('resourceGone()', function () { - - it('returns a 410 error statusCode', function (done) { - - expect(Boom.resourceGone().output.statusCode).to.equal(410); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.resourceGone('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('lengthRequired()', function () { - - it('returns a 411 error statusCode', function (done) { - - expect(Boom.lengthRequired().output.statusCode).to.equal(411); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.lengthRequired('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('preconditionFailed()', function () { - - it('returns a 412 error statusCode', function (done) { - - expect(Boom.preconditionFailed().output.statusCode).to.equal(412); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.preconditionFailed('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('entityTooLarge()', function () { - - it('returns a 413 error statusCode', function (done) { - - expect(Boom.entityTooLarge().output.statusCode).to.equal(413); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.entityTooLarge('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('uriTooLong()', function () { - - it('returns a 414 error statusCode', function (done) { - - expect(Boom.uriTooLong().output.statusCode).to.equal(414); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.uriTooLong('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('unsupportedMediaType()', function () { - - it('returns a 415 error statusCode', function (done) { - - expect(Boom.unsupportedMediaType().output.statusCode).to.equal(415); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.unsupportedMediaType('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('rangeNotSatisfiable()', function () { - - it('returns a 416 error statusCode', function (done) { - - expect(Boom.rangeNotSatisfiable().output.statusCode).to.equal(416); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.rangeNotSatisfiable('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('expectationFailed()', function () { - - it('returns a 417 error statusCode', function (done) { - - expect(Boom.expectationFailed().output.statusCode).to.equal(417); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.expectationFailed('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('badData()', function () { - - it('returns a 422 error statusCode', function (done) { - - expect(Boom.badData().output.statusCode).to.equal(422); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.badData('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('preconditionRequired()', function () { - - it('returns a 428 error statusCode', function (done) { - - expect(Boom.preconditionRequired().output.statusCode).to.equal(428); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.preconditionRequired('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('tooManyRequests()', function () { - - it('returns a 429 error statusCode', function (done) { - - expect(Boom.tooManyRequests().output.statusCode).to.equal(429); - done(); - }); - - it('sets the message with the passed-in message', function (done) { - - expect(Boom.tooManyRequests('my message').message).to.equal('my message'); - done(); - }); -}); - -describe('serverTimeout()', function () { - - it('returns a 503 error statusCode', function (done) { - - expect(Boom.serverTimeout().output.statusCode).to.equal(503); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.serverTimeout('my message').message).to.equal('my message'); - done(); - }); -}); - -describe('forbidden()', function () { - - it('returns a 403 error statusCode', function (done) { - - expect(Boom.forbidden().output.statusCode).to.equal(403); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.forbidden('my message').message).to.equal('my message'); - done(); - }); -}); - -describe('notFound()', function () { - - it('returns a 404 error statusCode', function (done) { - - expect(Boom.notFound().output.statusCode).to.equal(404); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.notFound('my message').message).to.equal('my message'); - done(); - }); -}); - -describe('internal()', function () { - - it('returns a 500 error statusCode', function (done) { - - expect(Boom.internal().output.statusCode).to.equal(500); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - var err = Boom.internal('my message'); - expect(err.message).to.equal('my message'); - expect(err.isServer).to.true(); - expect(err.output.payload.message).to.equal('An internal server error occurred'); - done(); - }); - - it('passes data on the callback if its passed in', function (done) { - - expect(Boom.internal('my message', { my: 'data' }).data.my).to.equal('data'); - done(); - }); - - it('returns an error with composite message', function (done) { - - try { - JSON.parse('{'); - } - catch (err) { - var boom = Boom.internal('Someting bad', err); - expect(boom.message).to.equal('Someting bad: Unexpected end of input'); - expect(boom.isServer).to.be.true(); - done(); - } - }); -}); - -describe('notImplemented()', function () { - - it('returns a 501 error statusCode', function (done) { - - expect(Boom.notImplemented().output.statusCode).to.equal(501); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.notImplemented('my message').message).to.equal('my message'); - done(); - }); -}); - - -describe('badGateway()', function () { - - it('returns a 502 error statusCode', function (done) { - - expect(Boom.badGateway().output.statusCode).to.equal(502); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.badGateway('my message').message).to.equal('my message'); - done(); - }); -}); - -describe('gatewayTimeout()', function () { - - it('returns a 504 error statusCode', function (done) { - - expect(Boom.gatewayTimeout().output.statusCode).to.equal(504); - done(); - }); - - it('sets the message with the passed in message', function (done) { - - expect(Boom.gatewayTimeout('my message').message).to.equal('my message'); - done(); - }); -}); - -describe('badImplementation()', function () { - - it('returns a 500 error statusCode', function (done) { - - var err = Boom.badImplementation(); - expect(err.output.statusCode).to.equal(500); - expect(err.isDeveloperError).to.equal(true); - expect(err.isServer).to.be.true(); - done(); - }); -}); - -describe('stack trace', function () { - - it('should omit lib', function (done) { - - ['badRequest', 'unauthorized', 'forbidden', 'notFound', 'methodNotAllowed', - 'notAcceptable', 'proxyAuthRequired', 'clientTimeout', 'conflict', - 'resourceGone', 'lengthRequired', 'preconditionFailed', 'entityTooLarge', - 'uriTooLong', 'unsupportedMediaType', 'rangeNotSatisfiable', 'expectationFailed', - 'badData', 'preconditionRequired', 'tooManyRequests', - - // 500s - 'internal', 'notImplemented', 'badGateway', 'serverTimeout', 'gatewayTimeout', - 'badImplementation' - ].forEach(function (name) { - - var err = Boom[name](); - expect(err.stack).to.not.match(/\/lib\/index\.js/); - }); - - done(); - }); -}); diff --git a/web/node_modules/brace-expansion/README.md b/web/node_modules/brace-expansion/README.md deleted file mode 100644 index ed2ec1f..0000000 --- a/web/node_modules/brace-expansion/README.md +++ /dev/null @@ -1,123 +0,0 @@ -# brace-expansion - -[Brace expansion](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html), -as known from sh/bash, in JavaScript. - -[![build status](https://secure.travis-ci.org/juliangruber/brace-expansion.svg)](http://travis-ci.org/juliangruber/brace-expansion) -[![downloads](https://img.shields.io/npm/dm/brace-expansion.svg)](https://www.npmjs.org/package/brace-expansion) -[![Greenkeeper badge](https://badges.greenkeeper.io/juliangruber/brace-expansion.svg)](https://greenkeeper.io/) - -[![testling badge](https://ci.testling.com/juliangruber/brace-expansion.png)](https://ci.testling.com/juliangruber/brace-expansion) - -## Example - -```js -var expand = require('brace-expansion'); - -expand('file-{a,b,c}.jpg') -// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg'] - -expand('-v{,,}') -// => ['-v', '-v', '-v'] - -expand('file{0..2}.jpg') -// => ['file0.jpg', 'file1.jpg', 'file2.jpg'] - -expand('file-{a..c}.jpg') -// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg'] - -expand('file{2..0}.jpg') -// => ['file2.jpg', 'file1.jpg', 'file0.jpg'] - -expand('file{0..4..2}.jpg') -// => ['file0.jpg', 'file2.jpg', 'file4.jpg'] - -expand('file-{a..e..2}.jpg') -// => ['file-a.jpg', 'file-c.jpg', 'file-e.jpg'] - -expand('file{00..10..5}.jpg') -// => ['file00.jpg', 'file05.jpg', 'file10.jpg'] - -expand('{{A..C},{a..c}}') -// => ['A', 'B', 'C', 'a', 'b', 'c'] - -expand('ppp{,config,oe{,conf}}') -// => ['ppp', 'pppconfig', 'pppoe', 'pppoeconf'] -``` - -## API - -```js -var expand = require('brace-expansion'); -``` - -### var expanded = expand(str) - -Return an array of all possible and valid expansions of `str`. If none are -found, `[str]` is returned. - -Valid expansions are: - -```js -/^(.*,)+(.+)?$/ -// {a,b,...} -``` - -A comma seperated list of options, like `{a,b}` or `{a,{b,c}}` or `{,a,}`. - -```js -/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/ -// {x..y[..incr]} -``` - -A numeric sequence from `x` to `y` inclusive, with optional increment. -If `x` or `y` start with a leading `0`, all the numbers will be padded -to have equal length. Negative numbers and backwards iteration work too. - -```js -/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/ -// {x..y[..incr]} -``` - -An alphabetic sequence from `x` to `y` inclusive, with optional increment. -`x` and `y` must be exactly one character, and if given, `incr` must be a -number. - -For compatibility reasons, the string `${` is not eligible for brace expansion. - -## Installation - -With [npm](https://npmjs.org) do: - -```bash -npm install brace-expansion -``` - -## Contributors - -- [Julian Gruber](https://github.com/juliangruber) -- [Isaac Z. Schlueter](https://github.com/isaacs) - -## License - -(MIT) - -Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/web/node_modules/brace-expansion/index.js b/web/node_modules/brace-expansion/index.js deleted file mode 100644 index 0478be8..0000000 --- a/web/node_modules/brace-expansion/index.js +++ /dev/null @@ -1,201 +0,0 @@ -var concatMap = require('concat-map'); -var balanced = require('balanced-match'); - -module.exports = expandTop; - -var escSlash = '\0SLASH'+Math.random()+'\0'; -var escOpen = '\0OPEN'+Math.random()+'\0'; -var escClose = '\0CLOSE'+Math.random()+'\0'; -var escComma = '\0COMMA'+Math.random()+'\0'; -var escPeriod = '\0PERIOD'+Math.random()+'\0'; - -function numeric(str) { - return parseInt(str, 10) == str - ? parseInt(str, 10) - : str.charCodeAt(0); -} - -function escapeBraces(str) { - return str.split('\\\\').join(escSlash) - .split('\\{').join(escOpen) - .split('\\}').join(escClose) - .split('\\,').join(escComma) - .split('\\.').join(escPeriod); -} - -function unescapeBraces(str) { - return str.split(escSlash).join('\\') - .split(escOpen).join('{') - .split(escClose).join('}') - .split(escComma).join(',') - .split(escPeriod).join('.'); -} - - -// Basically just str.split(","), but handling cases -// where we have nested braced sections, which should be -// treated as individual members, like {a,{b,c},d} -function parseCommaParts(str) { - if (!str) - return ['']; - - var parts = []; - var m = balanced('{', '}', str); - - if (!m) - return str.split(','); - - var pre = m.pre; - var body = m.body; - var post = m.post; - var p = pre.split(','); - - p[p.length-1] += '{' + body + '}'; - var postParts = parseCommaParts(post); - if (post.length) { - p[p.length-1] += postParts.shift(); - p.push.apply(p, postParts); - } - - parts.push.apply(parts, p); - - return parts; -} - -function expandTop(str) { - if (!str) - return []; - - // I don't know why Bash 4.3 does this, but it does. - // Anything starting with {} will have the first two bytes preserved - // but *only* at the top level, so {},a}b will not expand to anything, - // but a{},b}c will be expanded to [a}c,abc]. - // One could argue that this is a bug in Bash, but since the goal of - // this module is to match Bash's rules, we escape a leading {} - if (str.substr(0, 2) === '{}') { - str = '\\{\\}' + str.substr(2); - } - - return expand(escapeBraces(str), true).map(unescapeBraces); -} - -function identity(e) { - return e; -} - -function embrace(str) { - return '{' + str + '}'; -} -function isPadded(el) { - return /^-?0\d/.test(el); -} - -function lte(i, y) { - return i <= y; -} -function gte(i, y) { - return i >= y; -} - -function expand(str, isTop) { - var expansions = []; - - var m = balanced('{', '}', str); - if (!m || /\$$/.test(m.pre)) return [str]; - - var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body); - var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body); - var isSequence = isNumericSequence || isAlphaSequence; - var isOptions = m.body.indexOf(',') >= 0; - if (!isSequence && !isOptions) { - // {a},b} - if (m.post.match(/,.*\}/)) { - str = m.pre + '{' + m.body + escClose + m.post; - return expand(str); - } - return [str]; - } - - var n; - if (isSequence) { - n = m.body.split(/\.\./); - } else { - n = parseCommaParts(m.body); - if (n.length === 1) { - // x{{a,b}}y ==> x{a}y x{b}y - n = expand(n[0], false).map(embrace); - if (n.length === 1) { - var post = m.post.length - ? expand(m.post, false) - : ['']; - return post.map(function(p) { - return m.pre + n[0] + p; - }); - } - } - } - - // at this point, n is the parts, and we know it's not a comma set - // with a single entry. - - // no need to expand pre, since it is guaranteed to be free of brace-sets - var pre = m.pre; - var post = m.post.length - ? expand(m.post, false) - : ['']; - - var N; - - if (isSequence) { - var x = numeric(n[0]); - var y = numeric(n[1]); - var width = Math.max(n[0].length, n[1].length) - var incr = n.length == 3 - ? Math.abs(numeric(n[2])) - : 1; - var test = lte; - var reverse = y < x; - if (reverse) { - incr *= -1; - test = gte; - } - var pad = n.some(isPadded); - - N = []; - - for (var i = x; test(i, y); i += incr) { - var c; - if (isAlphaSequence) { - c = String.fromCharCode(i); - if (c === '\\') - c = ''; - } else { - c = String(i); - if (pad) { - var need = width - c.length; - if (need > 0) { - var z = new Array(need + 1).join('0'); - if (i < 0) - c = '-' + z + c.slice(1); - else - c = z + c; - } - } - } - N.push(c); - } - } else { - N = concatMap(n, function(el) { return expand(el, false) }); - } - - for (var j = 0; j < N.length; j++) { - for (var k = 0; k < post.length; k++) { - var expansion = pre + N[j] + post[k]; - if (!isTop || isSequence || expansion) - expansions.push(expansion); - } - } - - return expansions; -} - diff --git a/web/node_modules/brace-expansion/package.json b/web/node_modules/brace-expansion/package.json deleted file mode 100644 index ac6d3c0..0000000 --- a/web/node_modules/brace-expansion/package.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "_args": [ - [ - "brace-expansion@1.1.8", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "brace-expansion@1.1.8", - "_id": "brace-expansion@1.1.8", - "_inBundle": false, - "_integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "_location": "/brace-expansion", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "brace-expansion@1.1.8", - "name": "brace-expansion", - "escapedName": "brace-expansion", - "rawSpec": "1.1.8", - "saveSpec": null, - "fetchSpec": "1.1.8" - }, - "_requiredBy": [ - "/glob-stream/minimatch", - "/glob/minimatch", - "/minimatch" - ], - "_resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "_spec": "1.1.8", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "Julian Gruber", - "email": "mail@juliangruber.com", - "url": "http://juliangruber.com" - }, - "bugs": { - "url": "https://github.com/juliangruber/brace-expansion/issues" - }, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - }, - "description": "Brace expansion as known from sh/bash", - "devDependencies": { - "matcha": "^0.7.0", - "tape": "^4.6.0" - }, - "homepage": "https://github.com/juliangruber/brace-expansion", - "keywords": [], - "license": "MIT", - "main": "index.js", - "name": "brace-expansion", - "repository": { - "type": "git", - "url": "git://github.com/juliangruber/brace-expansion.git" - }, - "scripts": { - "bench": "matcha test/perf/bench.js", - "gentest": "bash test/generate.sh", - "test": "tape test/*.js" - }, - "testling": { - "files": "test/*.js", - "browsers": [ - "ie/8..latest", - "firefox/20..latest", - "firefox/nightly", - "chrome/25..latest", - "chrome/canary", - "opera/12..latest", - "opera/next", - "safari/5.1..latest", - "ipad/6.0..latest", - "iphone/6.0..latest", - "android-browser/4.2..latest" - ] - }, - "version": "1.1.8" -} diff --git a/web/node_modules/braces/LICENSE b/web/node_modules/braces/LICENSE deleted file mode 100644 index 39245ac..0000000 --- a/web/node_modules/braces/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014-2016, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/web/node_modules/braces/README.md b/web/node_modules/braces/README.md deleted file mode 100644 index 52fa756..0000000 --- a/web/node_modules/braces/README.md +++ /dev/null @@ -1,248 +0,0 @@ -# braces [![NPM version](https://img.shields.io/npm/v/braces.svg?style=flat)](https://www.npmjs.com/package/braces) [![NPM downloads](https://img.shields.io/npm/dm/braces.svg?style=flat)](https://npmjs.org/package/braces) [![Build Status](https://img.shields.io/travis/jonschlinkert/braces.svg?style=flat)](https://travis-ci.org/jonschlinkert/braces) - -Fastest brace expansion for node.js, with the most complete support for the Bash 4.3 braces specification. - -## Install - -Install with [npm](https://www.npmjs.com/): - -```sh -$ npm install braces --save -``` - -## Features - -* Complete support for the braces part of the [Bash 4.3 Brace Expansion](www.gnu.org/software/bash/). Braces passes [all of the relevant unit tests](#bash-4-3-support) from the spec. -* Expands comma-separated values: `a/{b,c}/d` => `['a/b/d', 'a/c/d']` -* Expands alphabetical or numerical ranges: `{1..3}` => `['1', '2', '3']` -* [Very fast](#benchmarks) -* [Special characters](./patterns.md) can be used to generate interesting patterns. - -## Example usage - -```js -var braces = require('braces'); - -braces('a/{x,y}/c{d}e') -//=> ['a/x/cde', 'a/y/cde'] - -braces('a/b/c/{x,y}') -//=> ['a/b/c/x', 'a/b/c/y'] - -braces('a/{x,{1..5},y}/c{d}e') -//=> ['a/x/cde', 'a/1/cde', 'a/y/cde', 'a/2/cde', 'a/3/cde', 'a/4/cde', 'a/5/cde'] -``` - -### Use case: fixtures - -> Use braces to generate test fixtures! - -**Example** - -```js -var braces = require('./'); -var path = require('path'); -var fs = require('fs'); - -braces('blah/{a..z}.js').forEach(function(fp) { - if (!fs.existsSync(path.dirname(fp))) { - fs.mkdirSync(path.dirname(fp)); - } - fs.writeFileSync(fp, ''); -}); -``` - -See the [tests](./test/test.js) for more examples and use cases (also see the [bash spec tests](./test/bash-mm-adjusted.js)); - -### Range expansion - -Uses [expand-range](https://github.com/jonschlinkert/expand-range) for range expansion. - -```js -braces('a{1..3}b') -//=> ['a1b', 'a2b', 'a3b'] - -braces('a{5..8}b') -//=> ['a5b', 'a6b', 'a7b', 'a8b'] - -braces('a{00..05}b') -//=> ['a00b', 'a01b', 'a02b', 'a03b', 'a04b', 'a05b'] - -braces('a{01..03}b') -//=> ['a01b', 'a02b', 'a03b'] - -braces('a{000..005}b') -//=> ['a000b', 'a001b', 'a002b', 'a003b', 'a004b', 'a005b'] - -braces('a{a..e}b') -//=> ['aab', 'abb', 'acb', 'adb', 'aeb'] - -braces('a{A..E}b') -//=> ['aAb', 'aBb', 'aCb', 'aDb', 'aEb'] -``` - -Pass a function as the last argument to customize range expansions: - -```js -var range = braces('x{a..e}y', function (str, i) { - return String.fromCharCode(str) + i; -}); - -console.log(range); -//=> ['xa0y', 'xb1y', 'xc2y', 'xd3y', 'xe4y'] -``` - -See [expand-range](https://github.com/jonschlinkert/expand-range) for benchmarks, tests and the full list of range expansion features. - -## Options - -### options.makeRe - -Type: `Boolean` - -Deafault: `false` - -Return a regex-optimal string. If you're using braces to generate regex, this will result in dramatically faster performance. - -**Examples** - -With the default settings (`{makeRe: false}`): - -```js -braces('{1..5}'); -//=> ['1', '2', '3', '4', '5'] -``` - -With `{makeRe: true}`: - -```js -braces('{1..5}', {makeRe: true}); -//=> ['[1-5]'] - -braces('{3..9..3}', {makeRe: true}); -//=> ['(3|6|9)'] -``` - -### options.bash - -Type: `Boolean` - -Default: `false` - -Enables complete support for the Bash specification. The downside is a 20-25% speed decrease. - -**Example** - -Using the default setting (`{bash: false}`): - -```js -braces('a{b}c'); -//=> ['abc'] -``` - -In bash (and minimatch), braces with one item are not expanded. To get the same result with braces, set `{bash: true}`: - -```js -braces('a{b}c', {bash: true}); -//=> ['a{b}c'] -``` - -### options.nodupes - -Type: `Boolean` - -Deafault: `true` - -Duplicates are removed by default. To keep duplicates, pass `{nodupes: false}` on the options - -## Bash 4.3 Support - -> Better support for Bash 4.3 than minimatch - -This project has comprehensive unit tests, including tests coverted from [Bash 4.3](www.gnu.org/software/bash/). Currently only 8 of 102 unit tests fail, and - -## Run benchmarks - -Install dev dependencies: - -```bash -npm i -d && npm benchmark -``` - -### Latest results - -```bash -#1: escape.js - brace-expansion.js x 114,934 ops/sec ±1.24% (93 runs sampled) - braces.js x 342,254 ops/sec ±0.84% (90 runs sampled) - -#2: exponent.js - brace-expansion.js x 12,359 ops/sec ±0.86% (96 runs sampled) - braces.js x 20,389 ops/sec ±0.71% (97 runs sampled) - -#3: multiple.js - brace-expansion.js x 114,469 ops/sec ±1.44% (94 runs sampled) - braces.js x 401,621 ops/sec ±0.87% (91 runs sampled) - -#4: nested.js - brace-expansion.js x 102,769 ops/sec ±1.55% (92 runs sampled) - braces.js x 314,088 ops/sec ±0.71% (98 runs sampled) - -#5: normal.js - brace-expansion.js x 157,577 ops/sec ±1.65% (91 runs sampled) - braces.js x 1,115,950 ops/sec ±0.74% (94 runs sampled) - -#6: range.js - brace-expansion.js x 138,822 ops/sec ±1.71% (91 runs sampled) - braces.js x 1,108,353 ops/sec ±0.85% (94 runs sampled) -``` - -## Related projects - -You might also be interested in these projects: - -* [expand-range](https://www.npmjs.com/package/expand-range): Fast, bash-like range expansion. Expand a range of numbers or letters, uppercase or lowercase. See… [more](https://www.npmjs.com/package/expand-range) | [homepage](https://github.com/jonschlinkert/expand-range) -* [fill-range](https://www.npmjs.com/package/fill-range): Fill in a range of numbers or letters, optionally passing an increment or multiplier to… [more](https://www.npmjs.com/package/fill-range) | [homepage](https://github.com/jonschlinkert/fill-range) -* [micromatch](https://www.npmjs.com/package/micromatch): Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch. | [homepage](https://github.com/jonschlinkert/micromatch) - -## Contributing - -Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/braces/issues/new). - -## Building docs - -Generate readme and API documentation with [verb](https://github.com/verbose/verb): - -```sh -$ npm install verb && npm run docs -``` - -Or, if [verb](https://github.com/verbose/verb) is installed globally: - -```sh -$ verb -``` - -## Running tests - -Install dev dependencies: - -```sh -$ npm install -d && npm test -``` - -## Author - -**Jon Schlinkert** - -* [github/jonschlinkert](https://github.com/jonschlinkert) -* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) - -## License - -Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert). -Released under the [MIT license](https://github.com/jonschlinkert/braces/blob/master/LICENSE). - -*** - -_This file was generated by [verb](https://github.com/verbose/verb), v0.9.0, on May 21, 2016._ \ No newline at end of file diff --git a/web/node_modules/braces/index.js b/web/node_modules/braces/index.js deleted file mode 100644 index 3b4c58d..0000000 --- a/web/node_modules/braces/index.js +++ /dev/null @@ -1,399 +0,0 @@ -/*! - * braces - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT license. - */ - -'use strict'; - -/** - * Module dependencies - */ - -var expand = require('expand-range'); -var repeat = require('repeat-element'); -var tokens = require('preserve'); - -/** - * Expose `braces` - */ - -module.exports = function(str, options) { - if (typeof str !== 'string') { - throw new Error('braces expects a string'); - } - return braces(str, options); -}; - -/** - * Expand `{foo,bar}` or `{1..5}` braces in the - * given `string`. - * - * @param {String} `str` - * @param {Array} `arr` - * @param {Object} `options` - * @return {Array} - */ - -function braces(str, arr, options) { - if (str === '') { - return []; - } - - if (!Array.isArray(arr)) { - options = arr; - arr = []; - } - - var opts = options || {}; - arr = arr || []; - - if (typeof opts.nodupes === 'undefined') { - opts.nodupes = true; - } - - var fn = opts.fn; - var es6; - - if (typeof opts === 'function') { - fn = opts; - opts = {}; - } - - if (!(patternRe instanceof RegExp)) { - patternRe = patternRegex(); - } - - var matches = str.match(patternRe) || []; - var m = matches[0]; - - switch(m) { - case '\\,': - return escapeCommas(str, arr, opts); - case '\\.': - return escapeDots(str, arr, opts); - case '\/.': - return escapePaths(str, arr, opts); - case ' ': - return splitWhitespace(str); - case '{,}': - return exponential(str, opts, braces); - case '{}': - return emptyBraces(str, arr, opts); - case '\\{': - case '\\}': - return escapeBraces(str, arr, opts); - case '${': - if (!/\{[^{]+\{/.test(str)) { - return arr.concat(str); - } else { - es6 = true; - str = tokens.before(str, es6Regex()); - } - } - - if (!(braceRe instanceof RegExp)) { - braceRe = braceRegex(); - } - - var match = braceRe.exec(str); - if (match == null) { - return [str]; - } - - var outter = match[1]; - var inner = match[2]; - if (inner === '') { return [str]; } - - var segs, segsLength; - - if (inner.indexOf('..') !== -1) { - segs = expand(inner, opts, fn) || inner.split(','); - segsLength = segs.length; - - } else if (inner[0] === '"' || inner[0] === '\'') { - return arr.concat(str.split(/['"]/).join('')); - - } else { - segs = inner.split(','); - if (opts.makeRe) { - return braces(str.replace(outter, wrap(segs, '|')), opts); - } - - segsLength = segs.length; - if (segsLength === 1 && opts.bash) { - segs[0] = wrap(segs[0], '\\'); - } - } - - var len = segs.length; - var i = 0, val; - - while (len--) { - var path = segs[i++]; - - if (/(\.[^.\/])/.test(path)) { - if (segsLength > 1) { - return segs; - } else { - return [str]; - } - } - - val = splice(str, outter, path); - - if (/\{[^{}]+?\}/.test(val)) { - arr = braces(val, arr, opts); - } else if (val !== '') { - if (opts.nodupes && arr.indexOf(val) !== -1) { continue; } - arr.push(es6 ? tokens.after(val) : val); - } - } - - if (opts.strict) { return filter(arr, filterEmpty); } - return arr; -} - -/** - * Expand exponential ranges - * - * `a{,}{,}` => ['a', 'a', 'a', 'a'] - */ - -function exponential(str, options, fn) { - if (typeof options === 'function') { - fn = options; - options = null; - } - - var opts = options || {}; - var esc = '__ESC_EXP__'; - var exp = 0; - var res; - - var parts = str.split('{,}'); - if (opts.nodupes) { - return fn(parts.join(''), opts); - } - - exp = parts.length - 1; - res = fn(parts.join(esc), opts); - var len = res.length; - var arr = []; - var i = 0; - - while (len--) { - var ele = res[i++]; - var idx = ele.indexOf(esc); - - if (idx === -1) { - arr.push(ele); - - } else { - ele = ele.split('__ESC_EXP__').join(''); - if (!!ele && opts.nodupes !== false) { - arr.push(ele); - - } else { - var num = Math.pow(2, exp); - arr.push.apply(arr, repeat(ele, num)); - } - } - } - return arr; -} - -/** - * Wrap a value with parens, brackets or braces, - * based on the given character/separator. - * - * @param {String|Array} `val` - * @param {String} `ch` - * @return {String} - */ - -function wrap(val, ch) { - if (ch === '|') { - return '(' + val.join(ch) + ')'; - } - if (ch === ',') { - return '{' + val.join(ch) + '}'; - } - if (ch === '-') { - return '[' + val.join(ch) + ']'; - } - if (ch === '\\') { - return '\\{' + val + '\\}'; - } -} - -/** - * Handle empty braces: `{}` - */ - -function emptyBraces(str, arr, opts) { - return braces(str.split('{}').join('\\{\\}'), arr, opts); -} - -/** - * Filter out empty-ish values - */ - -function filterEmpty(ele) { - return !!ele && ele !== '\\'; -} - -/** - * Handle patterns with whitespace - */ - -function splitWhitespace(str) { - var segs = str.split(' '); - var len = segs.length; - var res = []; - var i = 0; - - while (len--) { - res.push.apply(res, braces(segs[i++])); - } - return res; -} - -/** - * Handle escaped braces: `\\{foo,bar}` - */ - -function escapeBraces(str, arr, opts) { - if (!/\{[^{]+\{/.test(str)) { - return arr.concat(str.split('\\').join('')); - } else { - str = str.split('\\{').join('__LT_BRACE__'); - str = str.split('\\}').join('__RT_BRACE__'); - return map(braces(str, arr, opts), function(ele) { - ele = ele.split('__LT_BRACE__').join('{'); - return ele.split('__RT_BRACE__').join('}'); - }); - } -} - -/** - * Handle escaped dots: `{1\\.2}` - */ - -function escapeDots(str, arr, opts) { - if (!/[^\\]\..+\\\./.test(str)) { - return arr.concat(str.split('\\').join('')); - } else { - str = str.split('\\.').join('__ESC_DOT__'); - return map(braces(str, arr, opts), function(ele) { - return ele.split('__ESC_DOT__').join('.'); - }); - } -} - -/** - * Handle escaped dots: `{1\\.2}` - */ - -function escapePaths(str, arr, opts) { - str = str.split('\/.').join('__ESC_PATH__'); - return map(braces(str, arr, opts), function(ele) { - return ele.split('__ESC_PATH__').join('\/.'); - }); -} - -/** - * Handle escaped commas: `{a\\,b}` - */ - -function escapeCommas(str, arr, opts) { - if (!/\w,/.test(str)) { - return arr.concat(str.split('\\').join('')); - } else { - str = str.split('\\,').join('__ESC_COMMA__'); - return map(braces(str, arr, opts), function(ele) { - return ele.split('__ESC_COMMA__').join(','); - }); - } -} - -/** - * Regex for common patterns - */ - -function patternRegex() { - return /\${|( (?=[{,}])|(?=[{,}]) )|{}|{,}|\\,(?=.*[{}])|\/\.(?=.*[{}])|\\\.(?={)|\\{|\\}/; -} - -/** - * Braces regex. - */ - -function braceRegex() { - return /.*(\\?\{([^}]+)\})/; -} - -/** - * es6 delimiter regex. - */ - -function es6Regex() { - return /\$\{([^}]+)\}/; -} - -var braceRe; -var patternRe; - -/** - * Faster alternative to `String.replace()` when the - * index of the token to be replaces can't be supplied - */ - -function splice(str, token, replacement) { - var i = str.indexOf(token); - return str.substr(0, i) + replacement - + str.substr(i + token.length); -} - -/** - * Fast array map - */ - -function map(arr, fn) { - if (arr == null) { - return []; - } - - var len = arr.length; - var res = new Array(len); - var i = -1; - - while (++i < len) { - res[i] = fn(arr[i], i, arr); - } - - return res; -} - -/** - * Fast array filter - */ - -function filter(arr, cb) { - if (arr == null) return []; - if (typeof cb !== 'function') { - throw new TypeError('braces: filter expects a callback function.'); - } - - var len = arr.length; - var res = arr.slice(); - var i = 0; - - while (len--) { - if (!cb(arr[len], i++)) { - res.splice(len, 1); - } - } - return res; -} diff --git a/web/node_modules/braces/package.json b/web/node_modules/braces/package.json deleted file mode 100644 index 97e1c2b..0000000 --- a/web/node_modules/braces/package.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "_args": [ - [ - "braces@1.8.5", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "braces@1.8.5", - "_id": "braces@1.8.5", - "_inBundle": false, - "_integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "_location": "/braces", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "braces@1.8.5", - "name": "braces", - "escapedName": "braces", - "rawSpec": "1.8.5", - "saveSpec": null, - "fetchSpec": "1.8.5" - }, - "_requiredBy": [ - "/micromatch" - ], - "_resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "_spec": "1.8.5", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "Jon Schlinkert", - "url": "https://github.com/jonschlinkert" - }, - "bugs": { - "url": "https://github.com/jonschlinkert/braces/issues" - }, - "dependencies": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - }, - "description": "Fastest brace expansion for node.js, with the most complete support for the Bash 4.3 braces specification.", - "devDependencies": { - "benchmarked": "^0.1.5", - "brace-expansion": "^1.1.3", - "chalk": "^1.1.3", - "gulp-format-md": "^0.1.8", - "minimatch": "^3.0.0", - "minimist": "^1.2.0", - "mocha": "^2.4.5", - "should": "^8.3.1" - }, - "engines": { - "node": ">=0.10.0" - }, - "files": [ - "index.js" - ], - "homepage": "https://github.com/jonschlinkert/braces", - "keywords": [ - "alpha", - "alphabetical", - "bash", - "brace", - "expand", - "expansion", - "filepath", - "fill", - "fs", - "glob", - "globbing", - "letter", - "match", - "matches", - "matching", - "number", - "numerical", - "path", - "range", - "ranges", - "sh" - ], - "license": "MIT", - "main": "index.js", - "name": "braces", - "repository": { - "type": "git", - "url": "git+https://github.com/jonschlinkert/braces.git" - }, - "scripts": { - "test": "mocha" - }, - "verb": { - "plugins": [ - "gulp-format-md" - ], - "reflinks": [ - "verb" - ], - "toc": false, - "layout": "default", - "lint": { - "reflinks": true - }, - "tasks": [ - "readme" - ], - "related": { - "list": [ - "micromatch", - "expand-range", - "fill-range" - ] - } - }, - "version": "1.8.5" -} diff --git a/web/node_modules/browser-sync-client/README.md b/web/node_modules/browser-sync-client/README.md deleted file mode 100644 index 5f79a11..0000000 --- a/web/node_modules/browser-sync-client/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# browser-sync-client [![Build Status](https://travis-ci.org/BrowserSync/browser-sync-client.svg)](https://travis-ci.org/BrowserSync/browser-sync-client) - -Client-side script for BrowserSync - -## Contributors - -``` - 177 Shane Osbourne - 2 Sergey Slipchenko - 1 Hugo Dias - 1 Shinnosuke Watanabe - 1 Tim Schaub - 1 Shane Daniel - 1 Matthieu Vachon -``` - -## License -Copyright (c) 2014 Shane Osbourne -Licensed under the MIT license. diff --git a/web/node_modules/browser-sync-client/dist/.gitkeep b/web/node_modules/browser-sync-client/dist/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/web/node_modules/browser-sync-client/dist/index.js b/web/node_modules/browser-sync-client/dist/index.js deleted file mode 100755 index 912eaba..0000000 --- a/web/node_modules/browser-sync-client/dist/index.js +++ /dev/null @@ -1,1951 +0,0 @@ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o>> 0; - - // 4. If IsCallable(callback) is false, throw a TypeError exception. - // See: http://es5.github.com/#x9.11 - if (typeof callback !== 'function') { - throw new TypeError(callback + ' is not a function'); - } - - // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. - if (arguments.length > 1) { - T = thisArg; - } - - // 6. Let A be a new array created as if by the expression new Array(len) - // where Array is the standard built-in constructor with that name and - // len is the value of len. - A = new Array(len); - - // 7. Let k be 0 - k = 0; - - // 8. Repeat, while k < len - while (k < len) { - - var kValue, mappedValue; - - // a. Let Pk be ToString(k). - // This is implicit for LHS operands of the in operator - // b. Let kPresent be the result of calling the HasProperty internal - // method of O with argument Pk. - // This step can be combined with c - // c. If kPresent is true, then - if (k in O) { - - // i. Let kValue be the result of calling the Get internal - // method of O with argument Pk. - kValue = O[k]; - - // ii. Let mappedValue be the result of calling the Call internal - // method of callback with T as the this value and argument - // list containing kValue, k, and O. - mappedValue = callback.call(T, kValue, k, O); - - // iii. Call the DefineOwnProperty internal method of A with arguments - // Pk, Property Descriptor - // { Value: mappedValue, - // Writable: true, - // Enumerable: true, - // Configurable: true }, - // and false. - - // In browsers that support Object.defineProperty, use the following: - // Object.defineProperty(A, k, { - // value: mappedValue, - // writable: true, - // enumerable: true, - // configurable: true - // }); - - // For best browser support, use the following: - A[k] = mappedValue; - } - // d. Increase k by 1. - k++; - } - - // 9. return A - return A; - }; -} - -if (!Array.prototype.filter) { - Array.prototype.filter = function(fun/*, thisArg*/) { - 'use strict'; - - if (this === void 0 || this === null) { - throw new TypeError(); - } - - var t = Object(this); - var len = t.length >>> 0; - if (typeof fun !== 'function') { - throw new TypeError(); - } - - var res = []; - var thisArg = arguments.length >= 2 ? arguments[1] : void 0; - for (var i = 0; i < len; i++) { - if (i in t) { - var val = t[i]; - - // NOTE: Technically this should Object.defineProperty at - // the next index, as push can be affected by - // properties on Object.prototype and Array.prototype. - // But that method's new, and collisions should be - // rare, so use the more-compatible alternative. - if (fun.call(thisArg, val, i, t)) { - res.push(val); - } - } - } - - return res; - }; -} - -},{}],4:[function(require,module,exports){ -"use strict"; -var events = require("./events"); -var utils = require("./browser.utils"); -var emitter = require("./emitter"); -var sync = exports; - -var options = { - - tagNames: { - "css": "link", - "jpg": "img", - "jpeg": "img", - "png": "img", - "svg": "img", - "gif": "img", - "js": "script" - }, - attrs: { - "link": "href", - "img": "src", - "script": "src" - }, - blacklist: [ - // never allow .map files through - function(incoming) { - return incoming.ext === "map"; - } - ] -}; - -var hiddenElem; -var OPT_PATH = "codeSync"; - -var current = function () { - return window.location.pathname; -}; - -/** - * @param {BrowserSync} bs - */ -sync.init = function (bs) { - - if (bs.options.tagNames) { - options.tagNames = bs.options.tagNames; - } - - if (bs.options.scrollRestoreTechnique === "window.name") { - sync.saveScrollInName(emitter); - } else { - sync.saveScrollInCookie(utils.getWindow(), utils.getDocument()); - } - - bs.socket.on("file:reload", sync.reload(bs)); - bs.socket.on("browser:reload", function () { - if (bs.canSync({url: current()}, OPT_PATH)) { - sync.reloadBrowser(true, bs); - } - }); -}; - -/** - * Use window.name to store/restore scroll position - */ -sync.saveScrollInName = function () { - - var PRE = "<>"; - var SUF = "<>"; - var regex = new RegExp(PRE + "(.+?)" + SUF); - var $window = utils.getWindow(); - var saved = {}; - - /** - * Listen for the browser:hardReload event. - * When it runs, save the current scroll position - * in window.name - */ - emitter.on("browser:hardReload", function (data) { - var newname = [$window.name, PRE, JSON.stringify({ - bs: { - hardReload: true, - scroll: data.scrollPosition - } - }), SUF].join(""); - $window.name = newname; - }); - - /** - * On page load, check window.name for an existing - * BS json blob & parse it. - */ - try { - var json = $window.name.match(regex); - if (json) { - saved = JSON.parse(json[1]); - } - } catch (e) { - saved = {}; - } - - /** - * If the JSON was parsed correctly, try to - * find a scroll property and restore it. - */ - if (saved.bs && saved.bs.hardReload && saved.bs.scroll) { - utils.setScroll(saved.bs.scroll); - } - - /** - * Remove any existing BS json from window.name - * to ensure we don't interfere with any other - * libs who may be using it. - */ - $window.name = $window.name.replace(regex, ""); -}; - -/** - * Use a cookie-drop to save scroll position of - * @param $window - * @param $document - */ -sync.saveScrollInCookie = function ($window, $document) { - - if (!utils.isOldIe()) { - return; - } - - if ($document.readyState === "complete") { - utils.restoreScrollPosition(); - } else { - events.manager.addEvent($document, "readystatechange", function() { - if ($document.readyState === "complete") { - utils.restoreScrollPosition(); - } - }); - } - - emitter.on("browser:hardReload", utils.saveScrollPosition); -}; - -/** - * @param {string} search - * @param {string} key - * @param {string} suffix - */ -sync.updateSearch = function(search, key, suffix) { - - if (search === "") { - return "?" + suffix; - } - - return "?" + search - .slice(1) - .split("&") - .map(function (item) { - return item.split("="); - }) - .filter(function (tuple) { - return tuple[0] !== key; - }) - .map(function (item) { - return [item[0], item[1]].join("="); - }) - .concat(suffix) - .join("&"); -}; - -/** - * @param elem - * @param attr - * @param options - * @returns {{elem: HTMLElement, timeStamp: number}} - */ -sync.swapFile = function (elem, attr, options) { - - var currentValue = elem[attr]; - var timeStamp = new Date().getTime(); - var key = "rel"; - var suffix = key + "=" + timeStamp; - var anchor = utils.getLocation(currentValue); - var search = sync.updateSearch(anchor.search, key, suffix); - - if (options.timestamps === false) { - elem[attr] = anchor.href; - } else { - elem[attr] = anchor.href.split("?")[0] + search; - } - - var body = document.body; - - setTimeout(function () { - if (!hiddenElem) { - hiddenElem = document.createElement("DIV"); - body.appendChild(hiddenElem); - } else { - hiddenElem.style.display = "none"; - hiddenElem.style.display = "block"; - } - }, 200); - - return { - elem: elem, - timeStamp: timeStamp - }; -}; - -sync.getFilenameOnly = function (url) { - return /^[^\?]+(?=\?)/.exec(url); -}; - -/** - * @param {BrowserSync} bs - * @returns {*} - */ -sync.reload = function (bs) { - - /** - * @param data - from socket - */ - return function (data) { - - if (!bs.canSync({url: current()}, OPT_PATH)) { - return; - } - var transformedElem; - var options = bs.options; - var emitter = bs.emitter; - - if (data.url || !options.injectChanges) { - sync.reloadBrowser(true); - } - - if (data.basename && data.ext) { - - if (sync.isBlacklisted(data)) { - return; - } - - var domData = sync.getElems(data.ext); - var elems = sync.getMatches(domData.elems, data.basename, domData.attr); - - if (elems.length && options.notify) { - emitter.emit("notify", {message: "Injected: " + data.basename}); - } - - for (var i = 0, n = elems.length; i < n; i += 1) { - transformedElem = sync.swapFile(elems[i], domData.attr, options); - } - } - - return transformedElem; - }; -}; - -/** - * @param fileExtension - * @returns {*} - */ -sync.getTagName = function (fileExtension) { - return options.tagNames[fileExtension]; -}; - -/** - * @param tagName - * @returns {*} - */ -sync.getAttr = function (tagName) { - return options.attrs[tagName]; -}; - -/** - * @param incoming - * @returns {boolean} - */ -sync.isBlacklisted = function (incoming) { - return options.blacklist.some(function(fn) { - return fn(incoming); - }); -}; - -/** - * @param elems - * @param url - * @param attr - * @returns {Array} - */ -sync.getMatches = function (elems, url, attr) { - - if (url[0] === "*") { - return elems; - } - - var matches = []; - var urlMatcher = new RegExp("(^|/)" + url); - - for (var i = 0, len = elems.length; i < len; i += 1) { - if (urlMatcher.test(elems[i][attr])) { - matches.push(elems[i]); - } - } - - return matches; -}; - -/** - * @param fileExtension - * @returns {{elems: NodeList, attr: *}} - */ -sync.getElems = function(fileExtension) { - - var tagName = sync.getTagName(fileExtension); - var attr = sync.getAttr(tagName); - - return { - elems: document.getElementsByTagName(tagName), - attr: attr - }; -}; - -/** - * @param confirm - */ -sync.reloadBrowser = function (confirm) { - emitter.emit("browser:hardReload", { - scrollPosition: utils.getBrowserScrollPosition() - }); - if (confirm) { - utils.reloadBrowser(); - } -}; - -},{"./browser.utils":2,"./emitter":5,"./events":6}],5:[function(require,module,exports){ -"use strict"; - -exports.events = {}; - -/** - * @param name - * @param data - */ -exports.emit = function (name, data) { - var event = exports.events[name]; - var listeners; - if (event && event.listeners) { - listeners = event.listeners; - for (var i = 0, n = listeners.length; i < n; i += 1) { - listeners[i](data); - } - } -}; - -/** - * @param name - * @param func - */ -exports.on = function (name, func) { - var events = exports.events; - if (!events[name]) { - events[name] = { - listeners: [func] - }; - } else { - events[name].listeners.push(func); - } -}; -},{}],6:[function(require,module,exports){ -exports._ElementCache = function () { - - var cache = {}, - guidCounter = 1, - expando = "data" + (new Date).getTime(); - - this.getData = function (elem) { - var guid = elem[expando]; - if (!guid) { - guid = elem[expando] = guidCounter++; - cache[guid] = {}; - } - return cache[guid]; - }; - - this.removeData = function (elem) { - var guid = elem[expando]; - if (!guid) return; - delete cache[guid]; - try { - delete elem[expando]; - } - catch (e) { - if (elem.removeAttribute) { - elem.removeAttribute(expando); - } - } - }; -}; - -/** - * Fix an event - * @param event - * @returns {*} - */ -exports._fixEvent = function (event) { - - function returnTrue() { - return true; - } - - function returnFalse() { - return false; - } - - if (!event || !event.stopPropagation) { - var old = event || window.event; - - // Clone the old object so that we can modify the values - event = {}; - - for (var prop in old) { - event[prop] = old[prop]; - } - - // The event occurred on this element - if (!event.target) { - event.target = event.srcElement || document; - } - - // Handle which other element the event is related to - event.relatedTarget = event.fromElement === event.target ? - event.toElement : - event.fromElement; - - // Stop the default browser action - event.preventDefault = function () { - event.returnValue = false; - event.isDefaultPrevented = returnTrue; - }; - - event.isDefaultPrevented = returnFalse; - - // Stop the event from bubbling - event.stopPropagation = function () { - event.cancelBubble = true; - event.isPropagationStopped = returnTrue; - }; - - event.isPropagationStopped = returnFalse; - - // Stop the event from bubbling and executing other handlers - event.stopImmediatePropagation = function () { - this.isImmediatePropagationStopped = returnTrue; - this.stopPropagation(); - }; - - event.isImmediatePropagationStopped = returnFalse; - - // Handle mouse position - if (event.clientX != null) { - var doc = document.documentElement, body = document.body; - - event.pageX = event.clientX + - (doc && doc.scrollLeft || body && body.scrollLeft || 0) - - (doc && doc.clientLeft || body && body.clientLeft || 0); - event.pageY = event.clientY + - (doc && doc.scrollTop || body && body.scrollTop || 0) - - (doc && doc.clientTop || body && body.clientTop || 0); - } - - // Handle key presses - event.which = event.charCode || event.keyCode; - - // Fix button for mouse clicks: - // 0 == left; 1 == middle; 2 == right - if (event.button != null) { - event.button = (event.button & 1 ? 0 : - (event.button & 4 ? 1 : - (event.button & 2 ? 2 : 0))); - } - } - - return event; -}; - -/** - * @constructor - */ -exports._EventManager = function (cache) { - - var nextGuid = 1; - - this.addEvent = function (elem, type, fn) { - - var data = cache.getData(elem); - - if (!data.handlers) data.handlers = {}; - - if (!data.handlers[type]) - data.handlers[type] = []; - - if (!fn.guid) fn.guid = nextGuid++; - - data.handlers[type].push(fn); - - if (!data.dispatcher) { - data.disabled = false; - data.dispatcher = function (event) { - - if (data.disabled) return; - event = exports._fixEvent(event); - - var handlers = data.handlers[event.type]; - if (handlers) { - for (var n = 0; n < handlers.length; n++) { - handlers[n].call(elem, event); - } - } - }; - } - - if (data.handlers[type].length == 1) { - if (document.addEventListener) { - elem.addEventListener(type, data.dispatcher, false); - } - else if (document.attachEvent) { - elem.attachEvent("on" + type, data.dispatcher); - } - } - - }; - - function tidyUp(elem, type) { - - function isEmpty(object) { - for (var prop in object) { - return false; - } - return true; - } - - var data = cache.getData(elem); - - if (data.handlers[type].length === 0) { - - delete data.handlers[type]; - - if (document.removeEventListener) { - elem.removeEventListener(type, data.dispatcher, false); - } - else if (document.detachEvent) { - elem.detachEvent("on" + type, data.dispatcher); - } - } - - if (isEmpty(data.handlers)) { - delete data.handlers; - delete data.dispatcher; - } - - if (isEmpty(data)) { - cache.removeData(elem); - } - } - - this.removeEvent = function (elem, type, fn) { - - var data = cache.getData(elem); - - if (!data.handlers) return; - - var removeType = function (t) { - data.handlers[t] = []; - tidyUp(elem, t); - }; - - if (!type) { - for (var t in data.handlers) removeType(t); - return; - } - - var handlers = data.handlers[type]; - if (!handlers) return; - - if (!fn) { - removeType(type); - return; - } - - if (fn.guid) { - for (var n = 0; n < handlers.length; n++) { - if (handlers[n].guid === fn.guid) { - handlers.splice(n--, 1); - } - } - } - tidyUp(elem, type); - - }; - - this.proxy = function (context, fn) { - if (!fn.guid) { - fn.guid = nextGuid++; - } - var ret = function () { - return fn.apply(context, arguments); - }; - ret.guid = fn.guid; - return ret; - }; -}; - - - -/** - * Trigger a click on an element - * @param elem - */ -exports.triggerClick = function (elem) { - - var evObj; - - if (document.createEvent) { - window.setTimeout(function () { - evObj = document.createEvent("MouseEvents"); - evObj.initEvent("click", true, true); - elem.dispatchEvent(evObj); - }, 0); - } else { - window.setTimeout(function () { - if (document.createEventObject) { - evObj = document.createEventObject(); - evObj.cancelBubble = true; - elem.fireEvent("on" + "click", evObj); - } - }, 0); - } -}; - -var cache = new exports._ElementCache(); -var eventManager = new exports._EventManager(cache); - -eventManager.triggerClick = exports.triggerClick; - -exports.manager = eventManager; - - - - -},{}],7:[function(require,module,exports){ -"use strict"; - -/** - * This is the plugin for syncing clicks between browsers - * @type {string} - */ -var EVENT_NAME = "click"; -var OPT_PATH = "ghostMode.clicks"; -exports.canEmitEvents = true; - -/** - * @param {BrowserSync} bs - * @param eventManager - */ -exports.init = function (bs, eventManager) { - eventManager.addEvent(document.body, EVENT_NAME, exports.browserEvent(bs)); - bs.socket.on(EVENT_NAME, exports.socketEvent(bs, eventManager)); -}; - -/** - * Uses event delegation to determine the clicked element - * @param {BrowserSync} bs - * @returns {Function} - */ -exports.browserEvent = function (bs) { - - return function (event) { - - if (exports.canEmitEvents) { - - var elem = event.target || event.srcElement; - - if (elem.type === "checkbox" || elem.type === "radio") { - bs.utils.forceChange(elem); - return; - } - - bs.socket.emit(EVENT_NAME, bs.utils.getElementData(elem)); - - } else { - exports.canEmitEvents = true; - } - }; -}; - -/** - * @param {BrowserSync} bs - * @param {manager} eventManager - * @returns {Function} - */ -exports.socketEvent = function (bs, eventManager) { - - return function (data) { - - if (!bs.canSync(data, OPT_PATH) || bs.tabHidden) { - return false; - } - - var elem = bs.utils.getSingleElement(data.tagName, data.index); - - if (elem) { - exports.canEmitEvents = false; - eventManager.triggerClick(elem); - } - }; -}; -},{}],8:[function(require,module,exports){ -"use strict"; - -/** - * This is the plugin for syncing clicks between browsers - * @type {string} - */ -var EVENT_NAME = "input:text"; -var OPT_PATH = "ghostMode.forms.inputs"; -exports.canEmitEvents = true; - -/** - * @param {BrowserSync} bs - * @param eventManager - */ -exports.init = function (bs, eventManager) { - eventManager.addEvent(document.body, "keyup", exports.browserEvent(bs)); - bs.socket.on(EVENT_NAME, exports.socketEvent(bs, eventManager)); -}; - -/** - * @param {BrowserSync} bs - * @returns {Function} - */ -exports.browserEvent = function (bs) { - - return function (event) { - - var elem = event.target || event.srcElement; - var data; - - if (exports.canEmitEvents) { - - if (elem.tagName === "INPUT" || elem.tagName === "TEXTAREA") { - - data = bs.utils.getElementData(elem); - data.value = elem.value; - - bs.socket.emit(EVENT_NAME, data); - } - - } else { - exports.canEmitEvents = true; - } - }; -}; - -/** - * @param {BrowserSync} bs - * @returns {Function} - */ -exports.socketEvent = function (bs) { - - return function (data) { - - if (!bs.canSync(data, OPT_PATH)) { - return false; - } - - var elem = bs.utils.getSingleElement(data.tagName, data.index); - - if (elem) { - elem.value = data.value; - return elem; - } - - return false; - }; -}; -},{}],9:[function(require,module,exports){ -"use strict"; - -exports.plugins = { - "inputs": require("./ghostmode.forms.input"), - "toggles": require("./ghostmode.forms.toggles"), - "submit": require("./ghostmode.forms.submit") -}; - -/** - * Load plugins for enabled options - * @param bs - */ -exports.init = function (bs, eventManager) { - - var checkOpt = true; - var options = bs.options.ghostMode.forms; - - if (options === true) { - checkOpt = false; - } - - function init(name) { - exports.plugins[name].init(bs, eventManager); - } - - for (var name in exports.plugins) { - if (!checkOpt) { - init(name); - } else { - if (options[name]) { - init(name); - } - } - } -}; -},{"./ghostmode.forms.input":8,"./ghostmode.forms.submit":10,"./ghostmode.forms.toggles":11}],10:[function(require,module,exports){ -"use strict"; - -/** - * This is the plugin for syncing clicks between browsers - * @type {string} - */ -var EVENT_NAME = "form:submit"; -var OPT_PATH = "ghostMode.forms.submit"; -exports.canEmitEvents = true; - -/** - * @param {BrowserSync} bs - * @param eventManager - */ -exports.init = function (bs, eventManager) { - var browserEvent = exports.browserEvent(bs); - eventManager.addEvent(document.body, "submit", browserEvent); - eventManager.addEvent(document.body, "reset", browserEvent); - bs.socket.on(EVENT_NAME, exports.socketEvent(bs, eventManager)); -}; - -/** - * @param {BrowserSync} bs - * @returns {Function} - */ -exports.browserEvent = function (bs) { - - return function (event) { - if (exports.canEmitEvents) { - var elem = event.target || event.srcElement; - var data = bs.utils.getElementData(elem); - data.type = event.type; - bs.socket.emit(EVENT_NAME, data); - } else { - exports.canEmitEvents = true; - } - }; -}; - -/** - * @param {BrowserSync} bs - * @returns {Function} - */ -exports.socketEvent = function (bs) { - - return function (data) { - - if (!bs.canSync(data, OPT_PATH)) { - return false; - } - - var elem = bs.utils.getSingleElement(data.tagName, data.index); - - exports.canEmitEvents = false; - - if (elem && data.type === "submit") { - elem.submit(); - } - - if (elem && data.type === "reset") { - elem.reset(); - } - return false; - }; -}; -},{}],11:[function(require,module,exports){ -"use strict"; - -/** - * This is the plugin for syncing clicks between browsers - * @type {string} - */ -var EVENT_NAME = "input:toggles"; -var OPT_PATH = "ghostMode.forms.toggles"; -exports.canEmitEvents = true; - -/** - * @param {BrowserSync} bs - * @param eventManager - */ -exports.init = function (bs, eventManager) { - var browserEvent = exports.browserEvent(bs); - exports.addEvents(eventManager, browserEvent); - bs.socket.on(EVENT_NAME, exports.socketEvent(bs, eventManager)); -}; - -/** - * @param eventManager - * @param event - */ -exports.addEvents = function (eventManager, event) { - - var elems = document.getElementsByTagName("select"); - var inputs = document.getElementsByTagName("input"); - - addEvents(elems); - addEvents(inputs); - - function addEvents(domElems) { - for (var i = 0, n = domElems.length; i < n; i += 1) { - eventManager.addEvent(domElems[i], "change", event); - } - } -}; - -/** - * @param {BrowserSync} bs - * @returns {Function} - */ -exports.browserEvent = function (bs) { - - return function (event) { - - if (exports.canEmitEvents) { - var elem = event.target || event.srcElement; - var data; - if (elem.type === "radio" || elem.type === "checkbox" || elem.tagName === "SELECT") { - data = bs.utils.getElementData(elem); - data.type = elem.type; - data.value = elem.value; - data.checked = elem.checked; - bs.socket.emit(EVENT_NAME, data); - } - } else { - exports.canEmitEvents = true; - } - - }; -}; - -/** - * @param {BrowserSync} bs - * @returns {Function} - */ -exports.socketEvent = function (bs) { - - return function (data) { - - if (!bs.canSync(data, OPT_PATH)) { - return false; - } - - exports.canEmitEvents = false; - - var elem = bs.utils.getSingleElement(data.tagName, data.index); - - if (elem) { - if (data.type === "radio") { - elem.checked = true; - } - if (data.type === "checkbox") { - elem.checked = data.checked; - } - if (data.tagName === "SELECT") { - elem.value = data.value; - } - return elem; - } - return false; - }; -}; -},{}],12:[function(require,module,exports){ -"use strict"; - -var eventManager = require("./events").manager; - -exports.plugins = { - "scroll": require("./ghostmode.scroll"), - "clicks": require("./ghostmode.clicks"), - "forms": require("./ghostmode.forms"), - "location": require("./ghostmode.location") -}; - -/** - * Load plugins for enabled options - * @param bs - */ -exports.init = function (bs) { - for (var name in exports.plugins) { - if (bs.options.ghostMode[name]) { - exports.plugins[name].init(bs, eventManager); - } - } -}; -},{"./events":6,"./ghostmode.clicks":7,"./ghostmode.forms":9,"./ghostmode.location":13,"./ghostmode.scroll":14}],13:[function(require,module,exports){ -"use strict"; - -/** - * This is the plugin for syncing location - * @type {string} - */ -var EVENT_NAME = "browser:location"; -var OPT_PATH = "ghostMode.location"; -exports.canEmitEvents = true; - -/** - * @param {BrowserSync} bs - */ -exports.init = function (bs) { - bs.socket.on(EVENT_NAME, exports.socketEvent(bs)); -}; - -/** - * Respond to socket event - */ -exports.socketEvent = function (bs) { - - return function (data) { - - if (!bs.canSync(data, OPT_PATH)) { - return false; - } - - if (data.path) { - exports.setPath(data.path); - } else { - exports.setUrl(data.url); - } - }; -}; - -/** - * @param url - */ -exports.setUrl = function (url) { - window.location = url; -}; - -/** - * @param path - */ -exports.setPath = function (path) { - window.location = window.location.protocol + "//" + window.location.host + path; -}; -},{}],14:[function(require,module,exports){ -"use strict"; - -/** - * This is the plugin for syncing scroll between devices - * @type {string} - */ -var WINDOW_EVENT_NAME = "scroll"; -var ELEMENT_EVENT_NAME = "scroll:element"; -var OPT_PATH = "ghostMode.scroll"; -var utils; - -exports.canEmitEvents = true; - -/** - * @param {BrowserSync} bs - * @param eventManager - */ -exports.init = function (bs, eventManager) { - utils = bs.utils; - var opts = bs.options; - - /** - * Window Scroll events - */ - eventManager.addEvent(window, WINDOW_EVENT_NAME, exports.browserEvent(bs)); - bs.socket.on(WINDOW_EVENT_NAME, exports.socketEvent(bs)); - - /** - * element Scroll Events - */ - var cache = {}; - addElementScrollEvents("scrollElements", false); - addElementScrollEvents("scrollElementMapping", true); - bs.socket.on(ELEMENT_EVENT_NAME, exports.socketEventForElement(bs, cache)); - - function addElementScrollEvents (key, map) { - if (!opts[key] || !opts[key].length || !("querySelectorAll" in document)) { - return; - } - utils.forEach(opts[key], function (selector) { - var elems = document.querySelectorAll(selector) || []; - utils.forEach(elems, function (elem) { - var data = utils.getElementData(elem); - data.cacheSelector = data.tagName + ":" + data.index; - data.map = map; - cache[data.cacheSelector] = elem; - eventManager.addEvent(elem, WINDOW_EVENT_NAME, exports.browserEventForElement(bs, elem, data)); - }); - }); - } -}; - -/** - * @param {BrowserSync} bs - */ -exports.socketEvent = function (bs) { - - return function (data) { - - if (!bs.canSync(data, OPT_PATH)) { - return false; - } - - var scrollSpace = utils.getScrollSpace(); - - exports.canEmitEvents = false; - - if (bs.options && bs.options.scrollProportionally) { - return window.scrollTo(0, scrollSpace.y * data.position.proportional); // % of y axis of scroll to px - } else { - return window.scrollTo(0, data.position.raw.y); - } - }; -}; - -/** - * @param bs - */ -exports.socketEventForElement = function (bs, cache) { - return function (data) { - - if (!bs.canSync(data, OPT_PATH)) { - return false; - } - - exports.canEmitEvents = false; - - function scrollOne (selector, pos) { - if (cache[selector]) { - cache[selector].scrollTop = pos; - } - } - - if (data.map) { - return Object.keys(cache).forEach(function (key) { - scrollOne(key, data.position); - }); - } - - scrollOne(data.elem.cacheSelector, data.position); - }; -}; - -/** - * @param bs - */ -exports.browserEventForElement = function (bs, elem, data) { - return function () { - var canSync = exports.canEmitEvents; - if (canSync) { - bs.socket.emit(ELEMENT_EVENT_NAME, { - position: elem.scrollTop, - elem: data, - map: data.map - }); - } - exports.canEmitEvents = true; - }; -}; - -exports.browserEvent = function (bs) { - - return function () { - - var canSync = exports.canEmitEvents; - - if (canSync) { - bs.socket.emit(WINDOW_EVENT_NAME, { - position: exports.getScrollPosition() - }); - } - - exports.canEmitEvents = true; - }; -}; - - -/** - * @returns {{raw: number, proportional: number}} - */ -exports.getScrollPosition = function () { - var pos = utils.getBrowserScrollPosition(); - return { - raw: pos, // Get px of x and y axis of scroll - proportional: exports.getScrollTopPercentage(pos) // Get % of y axis of scroll - }; -}; - -/** - * @param {{x: number, y: number}} scrollSpace - * @param scrollPosition - * @returns {{x: number, y: number}} - */ -exports.getScrollPercentage = function (scrollSpace, scrollPosition) { - - var x = scrollPosition.x / scrollSpace.x; - var y = scrollPosition.y / scrollSpace.y; - - return { - x: x || 0, - y: y - }; -}; - -/** - * Get just the percentage of Y axis of scroll - * @returns {number} - */ -exports.getScrollTopPercentage = function (pos) { - var scrollSpace = utils.getScrollSpace(); - var percentage = exports.getScrollPercentage(scrollSpace, pos); - return percentage.y; -}; -},{}],15:[function(require,module,exports){ -"use strict"; - -var socket = require("./socket"); -var shims = require("./client-shims"); -var notify = require("./notify"); -var codeSync = require("./code-sync"); -var BrowserSync = require("./browser-sync"); -var ghostMode = require("./ghostmode"); -var emitter = require("./emitter"); -var events = require("./events"); -var utils = require("./browser.utils"); - -var shouldReload = false; -var initialised = false; - -/** - * @param options - */ -exports.init = function (options) { - if (shouldReload && options.reloadOnRestart) { - utils.reloadBrowser(); - } - - var BS = window.___browserSync___ || {}; - - if (!BS.client) { - - BS.client = true; - - var browserSync = new BrowserSync(options); - - // Always init on page load - ghostMode.init(browserSync); - codeSync.init(browserSync); - - notify.init(browserSync); - - if (options.notify) { - notify.flash("Connected to BrowserSync"); - } - } - - if (!initialised) { - socket.on("disconnect", function () { - if (options.notify) { - notify.flash("Disconnected from BrowserSync"); - } - shouldReload = true; - }); - initialised = true; - } -}; - -/** - * Handle individual socket connections - */ -socket.on("connection", exports.init); - -/**debug:start**/ -if (window.__karma__) { - window.__bs_scroll__ = require("./ghostmode.scroll"); - window.__bs_clicks__ = require("./ghostmode.clicks"); - window.__bs_location__ = require("./ghostmode.location"); - window.__bs_inputs__ = require("./ghostmode.forms.input"); - window.__bs_toggles__ = require("./ghostmode.forms.toggles"); - window.__bs_submit__ = require("./ghostmode.forms.submit"); - window.__bs_forms__ = require("./ghostmode.forms"); - window.__bs_utils__ = require("./browser.utils"); - window.__bs_emitter__ = emitter; - window.__bs = BrowserSync; - window.__bs_notify__ = notify; - window.__bs_code_sync__ = codeSync; - window.__bs_ghost_mode__ = ghostMode; - window.__bs_socket__ = socket; - window.__bs_index__ = exports; -} -/**debug:end**/ -},{"./browser-sync":1,"./browser.utils":2,"./client-shims":3,"./code-sync":4,"./emitter":5,"./events":6,"./ghostmode":12,"./ghostmode.clicks":7,"./ghostmode.forms":9,"./ghostmode.forms.input":8,"./ghostmode.forms.submit":10,"./ghostmode.forms.toggles":11,"./ghostmode.location":13,"./ghostmode.scroll":14,"./notify":16,"./socket":17}],16:[function(require,module,exports){ -"use strict"; - -var scroll = require("./ghostmode.scroll"); -var utils = require("./browser.utils"); - -var styles = { - display: "none", - padding: "15px", - fontFamily: "sans-serif", - position: "fixed", - fontSize: "0.9em", - zIndex: 9999, - right: 0, - top: 0, - borderBottomLeftRadius: "5px", - backgroundColor: "#1B2032", - margin: 0, - color: "white", - textAlign: "center", - pointerEvents: "none" -}; - -var elem; -var options; -var timeoutInt; - -/** - * @param {BrowserSync} bs - * @returns {*} - */ -exports.init = function (bs) { - - options = bs.options; - - var cssStyles = styles; - - if (options.notify.styles) { - - if (Object.prototype.toString.call(options.notify.styles) === "[object Array]") { - // handle original array behavior, replace all styles with a joined copy - cssStyles = options.notify.styles.join(";"); - } else { - for (var key in options.notify.styles) { - if (options.notify.styles.hasOwnProperty(key)) { - cssStyles[key] = options.notify.styles[key]; - } - } - } - } - - elem = document.createElement("DIV"); - elem.id = "__bs_notify__"; - - if (typeof cssStyles === "string") { - elem.style.cssText = cssStyles; - } else { - for (var rule in cssStyles) { - elem.style[rule] = cssStyles[rule]; - } - } - - var flashFn = exports.watchEvent(bs); - - bs.emitter.on("notify", flashFn); - bs.socket.on("browser:notify", flashFn); - - return elem; -}; - -/** - * @returns {Function} - */ -exports.watchEvent = function (bs) { - return function (data) { - if (bs.options.notify || data.override) { - if (typeof data === "string") { - return exports.flash(data); - } - exports.flash(data.message, data.timeout); - } - }; -}; - -/** - * - */ -exports.getElem = function () { - return elem; -}; - -/** - * @param message - * @param [timeout] - * @returns {*} - */ -exports.flash = function (message, timeout) { - - var elem = exports.getElem(); - var $body = utils.getBody(); - - // return if notify was never initialised - if (!elem) { - return false; - } - - elem.innerHTML = message; - elem.style.display = "block"; - - $body.appendChild(elem); - - if (timeoutInt) { - clearTimeout(timeoutInt); - timeoutInt = undefined; - } - - timeoutInt = window.setTimeout(function () { - elem.style.display = "none"; - if (elem.parentNode) { - $body.removeChild(elem); - } - }, timeout || 2000); - - return elem; -}; - -},{"./browser.utils":2,"./ghostmode.scroll":14}],17:[function(require,module,exports){ -"use strict"; - -/** - * @type {{emit: emit, on: on}} - */ -var BS = window.___browserSync___ || {}; -exports.socket = BS.socket || { - emit: function(){}, - on: function(){} -}; - - -/** - * @returns {string} - */ -exports.getPath = function () { - return window.location.pathname; -}; -/** - * Alias for socket.emit - * @param name - * @param data - */ -exports.emit = function (name, data) { - var socket = exports.socket; - if (socket && socket.emit) { - // send relative path of where the event is sent - data.url = exports.getPath(); - socket.emit(name, data); - } -}; - -/** - * Alias for socket.on - * @param name - * @param func - */ -exports.on = function (name, func) { - exports.socket.on(name, func); -}; -},{}],18:[function(require,module,exports){ -var utils = require("./browser.utils"); -var emitter = require("./emitter"); -var $document = utils.getDocument(); - -// Set the name of the hidden property and the change event for visibility -var hidden, visibilityChange; -if (typeof $document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support - hidden = "hidden"; - visibilityChange = "visibilitychange"; -} else if (typeof $document.mozHidden !== "undefined") { - hidden = "mozHidden"; - visibilityChange = "mozvisibilitychange"; -} else if (typeof $document.msHidden !== "undefined") { - hidden = "msHidden"; - visibilityChange = "msvisibilitychange"; -} else if (typeof $document.webkitHidden !== "undefined") { - hidden = "webkitHidden"; - visibilityChange = "webkitvisibilitychange"; -} - -// If the page is hidden, pause the video; -// if the page is shown, play the video -function handleVisibilityChange() { - if ($document[hidden]) { - emitter.emit("tab:hidden"); - } else { - emitter.emit("tab:visible"); - } -} - -if (typeof $document.addEventListener === "undefined" || - typeof $document[hidden] === "undefined") { - //console.log('not supported'); -} else { - $document.addEventListener(visibilityChange, handleVisibilityChange, false); -} -},{"./browser.utils":2,"./emitter":5}]},{},[15]); diff --git a/web/node_modules/browser-sync-client/dist/index.min.js b/web/node_modules/browser-sync-client/dist/index.min.js deleted file mode 100755 index 44609ce..0000000 --- a/web/node_modules/browser-sync-client/dist/index.min.js +++ /dev/null @@ -1 +0,0 @@ -!function t(e,n,o){function r(s,c){if(!n[s]){if(!e[s]){var a="function"==typeof require&&require;if(!c&&a)return a(s,!0);if(i)return i(s,!0);var l=new Error("Cannot find module '"+s+"'");throw l.code="MODULE_NOT_FOUND",l}var u=n[s]={exports:{}};e[s][0].call(u.exports,function(t){var n=e[s][1][t];return r(n?n:t)},u,u.exports,t,e,n,o)}return n[s].exports}for(var i="function"==typeof require&&require,s=0;sn;n++){if(!t||"object"!=typeof t)return!1;t=t[o[n]]}return"undefined"==typeof t?!1:t}var i=t("./socket"),s=t("./emitter"),c=(t("./notify"),t("./tab"),t("./browser.utils")),a=function(t){this.options=t,this.socket=i,this.emitter=s,this.utils=c,this.tabHidden=!1;var e=this;i.on("options:set",function(t){s.emit("notify","Setting options..."),e.options=t.options}),s.on("tab:hidden",function(){e.tabHidden=!0}),s.on("tab:visible",function(){e.tabHidden=!1})};a.prototype.canSync=function(t,e){if(t=t||{},t.override)return!0;var n=!0;return e&&(n=this.getOption(e)),n&&t.url===window.location.pathname},a.prototype.getOption=function(t){if(t&&t.match(/\./))return r(this.options,t);var e=this.options[t];return o(e)?!1:e},e.exports=a},{"./browser.utils":2,"./emitter":5,"./notify":16,"./socket":17,"./tab":18}],2:[function(t,e,n){"use strict";var o=n;o.getWindow=function(){return window},o.getDocument=function(){return document},o.getBody=function(){return document.getElementsByTagName("body")[0]},o.getBrowserScrollPosition=function(){var t,e,o=n.getWindow(),r=n.getDocument(),i=r.documentElement,s=r.body;return void 0!==o.pageYOffset?(t=o.pageXOffset,e=o.pageYOffset):(t=i.scrollLeft||s.scrollLeft||0,e=i.scrollTop||s.scrollTop||0),{x:t,y:e}},o.getScrollSpace=function(){var t=n.getDocument(),e=t.documentElement,o=t.body;return{x:o.scrollHeight-e.clientWidth,y:o.scrollHeight-e.clientHeight}},o.saveScrollPosition=function(){var t=o.getBrowserScrollPosition();t=[t.x,t.y],o.getDocument.cookie="bs_scroll_pos="+t.join(",")},o.restoreScrollPosition=function(){var t=o.getDocument().cookie.replace(/(?:(?:^|.*;\s*)bs_scroll_pos\s*\=\s*([^;]*).*$)|^.*$/,"$1").split(",");o.getWindow().scrollTo(t[0],t[1])},o.getElementIndex=function(t,e){var n=o.getDocument().getElementsByTagName(t);return Array.prototype.indexOf.call(n,e)},o.forceChange=function(t){t.blur(),t.focus()},o.getElementData=function(t){var e=t.tagName,n=o.getElementIndex(e,t);return{tagName:e,index:n}},o.getSingleElement=function(t,e){var n=o.getDocument().getElementsByTagName(t);return n[e]},o.getBody=function(){return o.getDocument().getElementsByTagName("body")[0]},o.setScroll=function(t){o.getWindow().scrollTo(t.x,t.y)},o.reloadBrowser=function(){o.getWindow().location.reload(!0)},o.forEach=function(t,e){for(var n=0,o=t.length;o>n;n+=1)e(t[n],n,t)},o.isOldIe=function(){return"undefined"!=typeof o.getWindow().attachEvent},o.getLocation=function(t){var e=o.getDocument().createElement("a");return e.href=t,""===e.host&&(e.href=e.href),e}},{}],3:[function(t,e,n){"indexOf"in Array.prototype||(Array.prototype.indexOf=function(t,e){void 0===e&&(e=0),0>e&&(e+=this.length),0>e&&(e=0);for(var n=this.length;n>e;e+=1)if(e in this&&this[e]===t)return e;return-1}),Array.prototype.map||(Array.prototype.map=function(t,e){var n,o,r;if(null==this)throw new TypeError(" this is null or not defined");var i=Object(this),s=i.length>>>0;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(arguments.length>1&&(n=e),o=new Array(s),r=0;s>r;){var c,a;r in i&&(c=i[r],a=t.call(n,c,r,i),o[r]=a),r++}return o}),Array.prototype.filter||(Array.prototype.filter=function(t){"use strict";if(void 0===this||null===this)throw new TypeError;var e=Object(this),n=e.length>>>0;if("function"!=typeof t)throw new TypeError;for(var o=[],r=arguments.length>=2?arguments[1]:void 0,i=0;n>i;i++)if(i in e){var s=e[i];t.call(r,s,i,e)&&o.push(s)}return o})},{}],4:[function(t,e,n){"use strict";var o,r=t("./events"),i=t("./browser.utils"),s=t("./emitter"),c=n,a={tagNames:{css:"link",jpg:"img",jpeg:"img",png:"img",svg:"img",gif:"img",js:"script"},attrs:{link:"href",img:"src",script:"src"},blacklist:[function(t){return"map"===t.ext}]},l="codeSync",u=function(){return window.location.pathname};c.init=function(t){t.options.tagNames&&(a.tagNames=t.options.tagNames),"window.name"===t.options.scrollRestoreTechnique?c.saveScrollInName(s):c.saveScrollInCookie(i.getWindow(),i.getDocument()),t.socket.on("file:reload",c.reload(t)),t.socket.on("browser:reload",function(){t.canSync({url:u()},l)&&c.reloadBrowser(!0,t)})},c.saveScrollInName=function(){var t="<>",e="<>",n=new RegExp(t+"(.+?)"+e),o=i.getWindow(),r={};s.on("browser:hardReload",function(n){var r=[o.name,t,JSON.stringify({bs:{hardReload:!0,scroll:n.scrollPosition}}),e].join("");o.name=r});try{var c=o.name.match(n);c&&(r=JSON.parse(c[1]))}catch(a){r={}}r.bs&&r.bs.hardReload&&r.bs.scroll&&i.setScroll(r.bs.scroll),o.name=o.name.replace(n,"")},c.saveScrollInCookie=function(t,e){i.isOldIe()&&("complete"===e.readyState?i.restoreScrollPosition():r.manager.addEvent(e,"readystatechange",function(){"complete"===e.readyState&&i.restoreScrollPosition()}),s.on("browser:hardReload",i.saveScrollPosition))},c.updateSearch=function(t,e,n){return""===t?"?"+n:"?"+t.slice(1).split("&").map(function(t){return t.split("=")}).filter(function(t){return t[0]!==e}).map(function(t){return[t[0],t[1]].join("=")}).concat(n).join("&")},c.swapFile=function(t,e,n){var r=t[e],s=(new Date).getTime(),a="rel",l=a+"="+s,u=i.getLocation(r),f=c.updateSearch(u.search,a,l);n.timestamps===!1?t[e]=u.href:t[e]=u.href.split("?")[0]+f;var d=document.body;return setTimeout(function(){o?(o.style.display="none",o.style.display="block"):(o=document.createElement("DIV"),d.appendChild(o))},200),{elem:t,timeStamp:s}},c.getFilenameOnly=function(t){return/^[^\?]+(?=\?)/.exec(t)},c.reload=function(t){return function(e){if(t.canSync({url:u()},l)){var n,o=t.options,r=t.emitter;if((e.url||!o.injectChanges)&&c.reloadBrowser(!0),e.basename&&e.ext){if(c.isBlacklisted(e))return;var i=c.getElems(e.ext),s=c.getMatches(i.elems,e.basename,i.attr);s.length&&o.notify&&r.emit("notify",{message:"Injected: "+e.basename});for(var a=0,f=s.length;f>a;a+=1)n=c.swapFile(s[a],i.attr,o)}return n}}},c.getTagName=function(t){return a.tagNames[t]},c.getAttr=function(t){return a.attrs[t]},c.isBlacklisted=function(t){return a.blacklist.some(function(e){return e(t)})},c.getMatches=function(t,e,n){if("*"===e[0])return t;for(var o=[],r=new RegExp("(^|/)"+e),i=0,s=t.length;s>i;i+=1)r.test(t[i][n])&&o.push(t[i]);return o},c.getElems=function(t){var e=c.getTagName(t),n=c.getAttr(e);return{elems:document.getElementsByTagName(e),attr:n}},c.reloadBrowser=function(t){s.emit("browser:hardReload",{scrollPosition:i.getBrowserScrollPosition()}),t&&i.reloadBrowser()}},{"./browser.utils":2,"./emitter":5,"./events":6}],5:[function(t,e,n){"use strict";n.events={},n.emit=function(t,e){var o,r=n.events[t];if(r&&r.listeners){o=r.listeners;for(var i=0,s=o.length;s>i;i+=1)o[i](e)}},n.on=function(t,e){var o=n.events;o[t]?o[t].listeners.push(e):o[t]={listeners:[e]}}},{}],6:[function(t,e,n){n._ElementCache=function(){var t={},e=1,n="data"+(new Date).getTime();this.getData=function(o){var r=o[n];return r||(r=o[n]=e++,t[r]={}),t[r]},this.removeData=function(e){var o=e[n];if(o){delete t[o];try{delete e[n]}catch(r){e.removeAttribute&&e.removeAttribute(n)}}}},n._fixEvent=function(t){function e(){return!0}function n(){return!1}if(!t||!t.stopPropagation){var o=t||window.event;t={};for(var r in o)t[r]=o[r];if(t.target||(t.target=t.srcElement||document),t.relatedTarget=t.fromElement===t.target?t.toElement:t.fromElement,t.preventDefault=function(){t.returnValue=!1,t.isDefaultPrevented=e},t.isDefaultPrevented=n,t.stopPropagation=function(){t.cancelBubble=!0,t.isPropagationStopped=e},t.isPropagationStopped=n,t.stopImmediatePropagation=function(){this.isImmediatePropagationStopped=e,this.stopPropagation()},t.isImmediatePropagationStopped=n,null!=t.clientX){var i=document.documentElement,s=document.body;t.pageX=t.clientX+(i&&i.scrollLeft||s&&s.scrollLeft||0)-(i&&i.clientLeft||s&&s.clientLeft||0),t.pageY=t.clientY+(i&&i.scrollTop||s&&s.scrollTop||0)-(i&&i.clientTop||s&&s.clientTop||0)}t.which=t.charCode||t.keyCode,null!=t.button&&(t.button=1&t.button?0:4&t.button?1:2&t.button?2:0)}return t},n._EventManager=function(t){function e(e,n){function o(t){for(var e in t)return!1;return!0}var r=t.getData(e);0===r.handlers[n].length&&(delete r.handlers[n],document.removeEventListener?e.removeEventListener(n,r.dispatcher,!1):document.detachEvent&&e.detachEvent("on"+n,r.dispatcher)),o(r.handlers)&&(delete r.handlers,delete r.dispatcher),o(r)&&t.removeData(e)}var o=1;this.addEvent=function(e,r,i){var s=t.getData(e);s.handlers||(s.handlers={}),s.handlers[r]||(s.handlers[r]=[]),i.guid||(i.guid=o++),s.handlers[r].push(i),s.dispatcher||(s.disabled=!1,s.dispatcher=function(t){if(!s.disabled){t=n._fixEvent(t);var o=s.handlers[t.type];if(o)for(var r=0;ro;o+=1)t.addEvent(n[o],"change",e)}var o=document.getElementsByTagName("select"),r=document.getElementsByTagName("input");n(o),n(r)},n.browserEvent=function(t){return function(e){if(n.canEmitEvents){var r,i=e.target||e.srcElement;("radio"===i.type||"checkbox"===i.type||"SELECT"===i.tagName)&&(r=t.utils.getElementData(i),r.type=i.type,r.value=i.value,r.checked=i.checked,t.socket.emit(o,r))}else n.canEmitEvents=!0}},n.socketEvent=function(t){return function(e){if(!t.canSync(e,r))return!1;n.canEmitEvents=!1;var o=t.utils.getSingleElement(e.tagName,e.index);return o?("radio"===e.type&&(o.checked=!0),"checkbox"===e.type&&(o.checked=e.checked),"SELECT"===e.tagName&&(o.value=e.value),o):!1}}},{}],12:[function(t,e,n){"use strict";var o=t("./events").manager;n.plugins={scroll:t("./ghostmode.scroll"),clicks:t("./ghostmode.clicks"),forms:t("./ghostmode.forms"),location:t("./ghostmode.location")},n.init=function(t){for(var e in n.plugins)t.options.ghostMode[e]&&n.plugins[e].init(t,o)}},{"./events":6,"./ghostmode.clicks":7,"./ghostmode.forms":9,"./ghostmode.location":13,"./ghostmode.scroll":14}],13:[function(t,e,n){"use strict";var o="browser:location",r="ghostMode.location";n.canEmitEvents=!0,n.init=function(t){t.socket.on(o,n.socketEvent(t))},n.socketEvent=function(t){return function(e){return t.canSync(e,r)?void(e.path?n.setPath(e.path):n.setUrl(e.url)):!1}},n.setUrl=function(t){window.location=t},n.setPath=function(t){window.location=window.location.protocol+"//"+window.location.host+t}},{}],14:[function(t,e,n){"use strict";var o,r="scroll",i="scroll:element",s="ghostMode.scroll";n.canEmitEvents=!0,n.init=function(t,e){function s(i,s){c[i]&&c[i].length&&"querySelectorAll"in document&&o.forEach(c[i],function(i){var c=document.querySelectorAll(i)||[];o.forEach(c,function(i){var c=o.getElementData(i);c.cacheSelector=c.tagName+":"+c.index,c.map=s,a[c.cacheSelector]=i,e.addEvent(i,r,n.browserEventForElement(t,i,c))})})}o=t.utils;var c=t.options;e.addEvent(window,r,n.browserEvent(t)),t.socket.on(r,n.socketEvent(t));var a={};s("scrollElements",!1),s("scrollElementMapping",!0),t.socket.on(i,n.socketEventForElement(t,a))},n.socketEvent=function(t){return function(e){if(!t.canSync(e,s))return!1;var r=o.getScrollSpace();return n.canEmitEvents=!1,t.options&&t.options.scrollProportionally?window.scrollTo(0,r.y*e.position.proportional):window.scrollTo(0,e.position.raw.y)}},n.socketEventForElement=function(t,e){return function(o){function r(t,n){e[t]&&(e[t].scrollTop=n)}return t.canSync(o,s)?(n.canEmitEvents=!1,o.map?Object.keys(e).forEach(function(t){r(t,o.position)}):void r(o.elem.cacheSelector,o.position)):!1}},n.browserEventForElement=function(t,e,o){return function(){var r=n.canEmitEvents;r&&t.socket.emit(i,{position:e.scrollTop,elem:o,map:o.map}),n.canEmitEvents=!0}},n.browserEvent=function(t){return function(){var e=n.canEmitEvents;e&&t.socket.emit(r,{position:n.getScrollPosition()}),n.canEmitEvents=!0}},n.getScrollPosition=function(){var t=o.getBrowserScrollPosition();return{raw:t,proportional:n.getScrollTopPercentage(t)}},n.getScrollPercentage=function(t,e){var n=e.x/t.x,o=e.y/t.y;return{x:n||0,y:o}},n.getScrollTopPercentage=function(t){var e=o.getScrollSpace(),r=n.getScrollPercentage(e,t);return r.y}},{}],15:[function(t,e,n){"use strict";var o=t("./socket"),r=(t("./client-shims"),t("./notify")),i=t("./code-sync"),s=t("./browser-sync"),c=t("./ghostmode"),a=(t("./emitter"),t("./events"),t("./browser.utils")),l=!1,u=!1;n.init=function(t){l&&t.reloadOnRestart&&a.reloadBrowser();var e=window.___browserSync___||{};if(!e.client){e.client=!0;var n=new s(t);c.init(n),i.init(n),r.init(n),t.notify&&r.flash("Connected to BrowserSync")}u||(o.on("disconnect",function(){t.notify&&r.flash("Disconnected from BrowserSync"),l=!0}),u=!0)},o.on("connection",n.init)},{"./browser-sync":1,"./browser.utils":2,"./client-shims":3,"./code-sync":4,"./emitter":5,"./events":6,"./ghostmode":12,"./ghostmode.clicks":7,"./ghostmode.forms":9,"./ghostmode.forms.input":8,"./ghostmode.forms.submit":10,"./ghostmode.forms.toggles":11,"./ghostmode.location":13,"./ghostmode.scroll":14,"./notify":16,"./socket":17}],16:[function(t,e,n){"use strict";var o,r,i,s=(t("./ghostmode.scroll"),t("./browser.utils")),c={display:"none",padding:"15px",fontFamily:"sans-serif",position:"fixed",fontSize:"0.9em",zIndex:9999,right:0,top:0,borderBottomLeftRadius:"5px",backgroundColor:"#1B2032",margin:0,color:"white",textAlign:"center",pointerEvents:"none"};n.init=function(t){r=t.options;var e=c;if(r.notify.styles)if("[object Array]"===Object.prototype.toString.call(r.notify.styles))e=r.notify.styles.join(";");else for(var i in r.notify.styles)r.notify.styles.hasOwnProperty(i)&&(e[i]=r.notify.styles[i]);if(o=document.createElement("DIV"),o.id="__bs_notify__","string"==typeof e)o.style.cssText=e;else for(var s in e)o.style[s]=e[s];var a=n.watchEvent(t);return t.emitter.on("notify",a),t.socket.on("browser:notify",a),o},n.watchEvent=function(t){return function(e){if(t.options.notify||e.override){if("string"==typeof e)return n.flash(e);n.flash(e.message,e.timeout)}}},n.getElem=function(){return o},n.flash=function(t,e){var o=n.getElem(),r=s.getBody();return o?(o.innerHTML=t,o.style.display="block",r.appendChild(o),i&&(clearTimeout(i),i=void 0),i=window.setTimeout(function(){o.style.display="none",o.parentNode&&r.removeChild(o)},e||2e3),o):!1}},{"./browser.utils":2,"./ghostmode.scroll":14}],17:[function(t,e,n){"use strict";var o=window.___browserSync___||{};n.socket=o.socket||{emit:function(){},on:function(){}},n.getPath=function(){return window.location.pathname},n.emit=function(t,e){var o=n.socket;o&&o.emit&&(e.url=n.getPath(),o.emit(t,e))},n.on=function(t,e){n.socket.on(t,e)}},{}],18:[function(t,e,n){function o(){a[r]?c.emit("tab:hidden"):c.emit("tab:visible")}var r,i,s=t("./browser.utils"),c=t("./emitter"),a=s.getDocument();"undefined"!=typeof a.hidden?(r="hidden",i="visibilitychange"):"undefined"!=typeof a.mozHidden?(r="mozHidden",i="mozvisibilitychange"):"undefined"!=typeof a.msHidden?(r="msHidden",i="msvisibilitychange"):"undefined"!=typeof a.webkitHidden&&(r="webkitHidden",i="webkitvisibilitychange"),"undefined"==typeof a.addEventListener||"undefined"==typeof a[r]||a.addEventListener(i,o,!1)},{"./browser.utils":2,"./emitter":5}]},{},[15]); \ No newline at end of file diff --git a/web/node_modules/browser-sync-client/index.js b/web/node_modules/browser-sync-client/index.js deleted file mode 100644 index f3121a4..0000000 --- a/web/node_modules/browser-sync-client/index.js +++ /dev/null @@ -1,144 +0,0 @@ -"use strict"; - -var etag = require("etag"); -var fresh = require("fresh"); -var fs = require("fs"); -var path = require("path"); -var zlib = require("zlib"); - -var minifiedScript = path.join(__dirname, "/dist/index.min.js"); -var unminifiedScript = path.join(__dirname, "/dist/index.js"); - -/** - * Does the current request support compressed encoding? - * @param {Object} req - * @returns {boolean} - */ -function supportsGzip (req) { - var accept = req.headers['accept-encoding']; - return accept && accept.indexOf('gzip') > -1; -} - -/** - * Set headers on the response - * @param {Object} res - * @param {String} body - */ -function setHeaders(res, body) { - - res.setHeader("Cache-Control", "public, max-age=0"); - res.setHeader("Content-Type", "text/javascript"); - res.setHeader("ETag", etag(body)); -} - -/** - * @param {Object} options - * @param {String} connector - * @returns {String} - */ -function getScriptBody(options, connector) { - - var script = minifiedScript; - - if (options && !options.minify) { - script = unminifiedScript; - } - - return connector + fs.readFileSync(script); -} - -/** - * @param {Object} req - * @returns {String} - */ -function isConditionalGet(req) { - return req.headers["if-none-match"] || req.headers["if-modified-since"]; -} - -/** - * Return a not-modified response - * @param {Object} res - */ -function notModified(res) { - res.removeHeader("Content-Type"); - res.statusCode = 304; - res.end(); -} - -/** - * Public method for returning either a middleware fn - * or the content as a string - * @param {Object} options - * @param {String} connector - content to be prepended - * @param {String} type - either `file` or `middleware` - * @returns {*} - */ -function init(options, connector, type) { - - var gzipCached; - - /** - * Combine string to create the final version - * @type {String} - */ - var requestBody = getScriptBody(options, connector); - - /** - * If the user asked for a file, simply return the string. - */ - if (type && type === "file") { - return requestBody; - } - - /** - * Otherwise return a function to be used a middleware - */ - return function (req, res) { - - /** - * default to using the uncompressed string - * @type {String} - */ - var output = requestBody; - - /** - * Set the appropriate headers for caching - */ - setHeaders(res, output); - - if (isConditionalGet(req) && fresh(req.headers, res._headers)) { - return notModified(res); - } - - /** - * If gzip is supported, compress the string once - * and save for future requests - */ - if (supportsGzip(req)) { - - res.setHeader("Content-Encoding", "gzip"); - - if (!gzipCached) { - var buf = new Buffer(output, "utf-8"); - zlib.gzip(buf, function (_, result) { - gzipCached = result; - res.end(result); - }); - } else { - res.end(gzipCached); - } - - } else { - res.end(output); - } - }; -} - -module.exports.middleware = init; -module.exports.plugin = init; -module.exports.minified = function () { - return fs.readFileSync(minifiedScript, 'utf8'); -}; -module.exports.unminified = function () { - return fs.readFileSync(unminifiedScript, 'utf8'); -} \ No newline at end of file diff --git a/web/node_modules/browser-sync-client/package.json b/web/node_modules/browser-sync-client/package.json deleted file mode 100644 index f9c3c63..0000000 --- a/web/node_modules/browser-sync-client/package.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "_args": [ - [ - "browser-sync-client@2.5.1", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "browser-sync-client@2.5.1", - "_id": "browser-sync-client@2.5.1", - "_inBundle": false, - "_integrity": "sha1-7BrWmknC4tS2RbGLHAbCmz2a+Os=", - "_location": "/browser-sync-client", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "browser-sync-client@2.5.1", - "name": "browser-sync-client", - "escapedName": "browser-sync-client", - "rawSpec": "2.5.1", - "saveSpec": null, - "fetchSpec": "2.5.1" - }, - "_requiredBy": [ - "/browser-sync" - ], - "_resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.5.1.tgz", - "_spec": "2.5.1", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "Shane Osbourne", - "email": "shane.osbourne8@gmail.com" - }, - "bugs": { - "url": "https://github.com/shakyshane/browser-sync-client/issues" - }, - "dependencies": { - "etag": "^1.7.0", - "fresh": "^0.3.0" - }, - "description": "Client-side scripts for BrowserSync", - "devDependencies": { - "browser-sync": "^2.9.11", - "browserify": "^11.2.0", - "chai": "~1.9.0", - "crossbow": "latest", - "express": "^4.12.3", - "gulp-contribs": "0.0.2", - "gulp-jshint": "~1.4.0", - "gulp-rename": "^1.2.2", - "gulp-uglify": "^0.2.1", - "karma": "^0.13.15", - "karma-chrome-launcher": "^0.1.3", - "karma-coverage": "^0.2.1", - "karma-firefox-launcher": "^0.1.4", - "karma-html2js-preprocessor": "^0.1.0", - "karma-mocha": "~0.1.1", - "karma-sinon": "~1.0.0", - "mocha": "^1.18.2", - "nodemon": "^1.11.0", - "sinon": "~1.8.2", - "supertest": "^0.10.0", - "through2": "^0.4.1", - "vinyl-fs": "^2.4.4", - "vinyl-source-stream": "^1.1.0" - }, - "engines": { - "node": ">=4.0.0" - }, - "files": [ - "dist", - "index.js" - ], - "homepage": "https://github.com/shakyshane/browser-sync-client", - "keywords": [], - "licenses": [ - { - "type": "MIT", - "url": "https://github.com/shakyshane/browser-sync-client/blob/master/LICENSE-MIT" - } - ], - "main": "index.js", - "name": "browser-sync-client", - "repository": { - "type": "git", - "url": "git://github.com/shakyshane/browser-sync-client.git" - }, - "scripts": { - "prepublish": "cb run default", - "start": "cb dev", - "test": "cb test" - }, - "version": "2.5.1" -} diff --git a/web/node_modules/browser-sync-ui/LICENSE b/web/node_modules/browser-sync-ui/LICENSE deleted file mode 100644 index f8fdc78..0000000 --- a/web/node_modules/browser-sync-ui/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [2015] [Shane Osbourne] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS,gs - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/README.md b/web/node_modules/browser-sync-ui/README.md deleted file mode 100644 index 1653b14..0000000 --- a/web/node_modules/browser-sync-ui/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Browsersync UI [![Build Status](https://travis-ci.org/BrowserSync/UI.svg?branch=master)](https://travis-ci.org/BrowserSync/UI) - -Comes bundled with the Browsersync module (version `2.0.0` onwards). - -## License -Copyright (c) 2016 Shane Osbourne -Licensed under the Apache 2.0 license. diff --git a/web/node_modules/browser-sync-ui/index.js b/web/node_modules/browser-sync-ui/index.js deleted file mode 100644 index 1fca4bd..0000000 --- a/web/node_modules/browser-sync-ui/index.js +++ /dev/null @@ -1,48 +0,0 @@ -"use strict"; - -var UI = require("./lib/UI"); -var config = require("./lib/config"); -var Events = require("events").EventEmitter; - -/** - * Hooks are for attaching functionality to BrowserSync - */ -module.exports.hooks = { - /** - * Client JS is added to each connected client - */ - "client:js": fileContent(config.defaults.clientJs) -}; - -/** - * BrowserSync Plugin interface - * @param {Object} opts - * @param {BrowserSync} bs - * @param {Function} cb - * @returns {UI} - */ -module.exports["plugin"] = function (opts, bs, cb) { - var ui = new UI(opts, bs, new Events()); - bs.setOption("session", new Date().getTime()); - ui.cb = cb || function () { /*noop*/ }; - ui.init(); - return ui; -}; - -module.exports["plugin:name"] = config.defaults.pluginName; - -/** - * @param filepath - * @returns {*} - */ -function getPath (filepath) { - return require("path").join(__dirname, filepath); -} - -/** - * @param filepath - * @returns {*} - */ -function fileContent (filepath) { - return require("fs").readFileSync(getPath(filepath)); -} \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/UI.js b/web/node_modules/browser-sync-ui/lib/UI.js deleted file mode 100644 index d007092..0000000 --- a/web/node_modules/browser-sync-ui/lib/UI.js +++ /dev/null @@ -1,250 +0,0 @@ -var fs = require("fs"); -var path = require("path"); - -var config = require("./config"); -var eachSeries = require("async-each-series"); -var asyncTasks = require("./async-tasks"); -var hooks = require("./hooks"); -var merge = require("./opts").merge; - -var defaultPlugins = { - "sync-options": require("./plugins/sync-options/sync-options.plugin"), - "overview": require("./plugins/overview/overview.plugin"), - "history": require("./plugins/history/history.plugin"), - "plugins": require("./plugins/plugins/plugins.plugin"), - "remote-debug": require("./plugins/remote-debug/remote-debug.plugin"), - "help": require("./plugins/help/help.plugin"), - "connections": require("./plugins/connections/connections.plugin"), - "network-throttle": require("./plugins/network-throttle/network-throttle.plugin") -}; - -/** - * @param {Object} opts - Any options specifically - * passed to the control panel - * @param {BrowserSync} bs - * @param {EventEmitter} emitter - * @constructor - * @returns {UI} - */ -var UI = function (opts, bs, emitter) { - - var ui = this; - ui.bs = bs; - ui.config = config.merge(); - ui.events = emitter; - ui.options = merge(opts); - ui.logger = bs.getLogger(ui.config.get("pluginName")); - ui.defaultPlugins = defaultPlugins; - ui.listeners = {}; - ui.clients = bs.io.of(bs.options.getIn(["socket", "namespace"])); - ui.socket = bs.io.of(ui.config.getIn(["socket", "namespace"])); - - if (ui.options.get("logLevel")) { - ui.logger.setLevel(ui.options.get("logLevel")); - } - - /** - * - */ - ui.pluginManager = new bs.utils.easyExtender(defaultPlugins, hooks).init(); - - /** - * Transform/save data RE: plugins - * @type {*} - */ - ui.bsPlugins = require("./resolve-plugins")(bs.getUserPlugins()); - - return ui; -}; - -/** - * Detect an available port - * @returns {UI} - */ -UI.prototype.init = function () { - - var ui = this; - - eachSeries( - asyncTasks, - taskRunner(ui), - tasksComplete(ui) - ); - - return this; -}; - -/** - * @param cb - */ -UI.prototype.getServer = function (cb) { - var ui = this; - if (ui.server) { - return ui.server; - } - this.events.on("ui:running", function () { - cb(null, ui.server); - }); -}; - -/** - * @returns {Array} - */ -UI.prototype.getInitialTemplates = function () { - var prefix = path.resolve(__dirname, "../templates/directives"); - return fs.readdirSync(prefix) - .map(function (name) { - return path.resolve(prefix, name); - }); -}; - -/** - * @param event - */ -UI.prototype.delegateEvent = function (event) { - - var ui = this; - var listeners = ui.listeners[event.namespace]; - - if (listeners) { - if (listeners.event) { - listeners.event.call(ui, event); - } else { - if (event.event && listeners[event.event]) { - listeners[event.event].call(ui, event.data); - } - } - } -}; - -/** - * @param cb - */ -UI.prototype.listen = function (ns, events) { - var ui = this; - if (Array.isArray(ns)) { - ns = ns.join(":"); - } - if (!ui.listeners[ns]) { - ui.listeners[ns] = events; - } -}; - -/** - * @param name - * @param value - * @returns {Map|*} - */ -UI.prototype.setOption = function (name, value) { - var ui = this; - ui.options = ui.options.set(name, value); - return ui.options; -}; - -/** - * @param path - * @param value - * @returns {Map|*} - */ -UI.prototype.setOptionIn = function (path, value) { - this.options = this.options.setIn(path, value); - return this.options; -}; - -/** - * @param fn - */ -UI.prototype.setMany = function (fn) { - this.options = this.options.withMutations(fn); - return this.options; -}; - -/** - * @param path - * @returns {any|*} - */ -UI.prototype.getOptionIn = function (path) { - return this.options.getIn(path); -}; - -/** - * Run each setup task in sequence - * @param ui - * @returns {Function} - */ -function taskRunner (ui) { - - return function (item, cb) { - - ui.logger.debug("Starting Step: " + item.step); - - /** - * Give each step access to the UI Instance - */ - item.fn(ui, function (err, out) { - if (err) { - return cb(err); - } - if (out) { - handleOut(ui, out); - } - ui.logger.debug("{green:Step Complete: " + item.step); - cb(); - }); - }; -} - -/** - * Setup tasks may return options or instance properties to be set - * @param {UI} ui - * @param {Object} out - */ -function handleOut (ui, out) { - - if (out.options) { - Object.keys(out.options).forEach(function (key) { - ui.options = ui.options.set(key, out.options[key]); - }); - } - - if (out.optionsIn) { - out.optionsIn.forEach(function (item) { - ui.options = ui.options.setIn(item.path, item.value); - }); - } - - if (out.instance) { - Object.keys(out.instance).forEach(function (key) { - ui[key] = out.instance[key]; - }); - } -} - -/** - * All async tasks complete at this point - * @param ui - */ -function tasksComplete (ui) { - - return function (err) { - - /** - * Log any error according to BrowserSync's Logging level - */ - if (err) { - ui.logger.setOnce("useLevelPrefixes", true).error(err.message || err); - } - - /** - * Running event - */ - ui.events.emit("ui:running", {instance: ui, options: ui.options}); - - /** - * Finally call the user-provided callback - */ - ui.cb(null, ui); - }; -} - -module.exports = UI; \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/async-tasks.js b/web/node_modules/browser-sync-ui/lib/async-tasks.js deleted file mode 100644 index 7d7f6e2..0000000 --- a/web/node_modules/browser-sync-ui/lib/async-tasks.js +++ /dev/null @@ -1,36 +0,0 @@ -var async = require("./async"); - -module.exports = [ - { - step: "Setting default plugins", - fn: async.initDefaultHooks - }, - { - step: "Finding a free port", - fn: async.findAFreePort - }, - { - step: "Setting options also relevant to UI from BS", - fn: async.setBsOptions - }, - { - step: "Setting available URLS for UI", - fn: async.setUrlOptions - }, - { - step: "Starting the Control Panel Server", - fn: async.startServer - }, - { - step: "Add element events", - fn: async.addElementEvents - }, - { - step: "Registering default plugins", - fn: async.registerPlugins - }, - { - step: "Add options setting event", - fn: async.addOptionsEvent - } -]; \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/async.js b/web/node_modules/browser-sync-ui/lib/async.js deleted file mode 100644 index cff0427..0000000 --- a/web/node_modules/browser-sync-ui/lib/async.js +++ /dev/null @@ -1,204 +0,0 @@ -var Immutable = require("immutable"); -var url = require("url"); - -module.exports = { - /** - * The UI uses it's own server/port - * @param ui - * @param done - */ - findAFreePort: function (ui, done) { - var port = ui.options.get("port"); - ui.bs.utils.portscanner.findAPortNotInUse(port, port + 100, { - host: "localhost", - timeout: 1000 - }, function (err, port) { - if (err) { - return done(err); - } - done(null, { - options: { - port: port - } - }); - }); - }, - /** - * Default hooks do things like creating/joining JS files & - * building angular config - * @param ui - * @param done - */ - initDefaultHooks: function (ui, done) { - - var out = ui.pluginManager.hook("page", ui); - - done(null, { - instance: { - clientJs: ui.pluginManager.hook("client:js", ui), - templates: ui.pluginManager.hook("templates", ui.getInitialTemplates(), ui), - pagesConfig: out.pagesConfig, - pages: out.pagesObj, - pageMarkup: out.pageMarkup - } - }); - }, - setBsOptions: function (ui, done) { - done(null, { - options: { - bs: Immutable.Map({ - mode: ui.bs.options.get("mode"), - port: ui.bs.options.get("port") - }) - } - }); - }, - /** - * @param ui - * @param done - */ - setUrlOptions: function (ui, done) { - - var port = ui.options.get("port"); - var bsUrls = ui.bs.getOptionIn(["urls"]).toJS(); - var urls = { - ui: "http://localhost:" + port - }; - - if (bsUrls.external) { - urls["ui-external"] = ["http://", url.parse(bsUrls.external).hostname, ":", port].join(""); - } - - done(null, { - options: { - urls: Immutable.fromJS(urls) - } - }); - }, - /** - * Simple static file server with some middlewares for custom - * scripts/routes. - * @param ui - * @param done - */ - startServer: function (ui, done) { - - var bs = ui.bs; - var port = ui.options.get("port"); - - ui.logger.debug("Using port %s", port); - - var server = require("./server")(ui, { - middleware: { - socket: bs.getMiddleware("socket-js"), - connector: bs.getSocketConnector(bs.options.get("port"), { - path: bs.options.getIn(["socket", "path"]), - namespace: ui.config.getIn(["socket", "namespace"]) - }) - } - }); - - require('server-destroy')(server.server); - - bs.registerCleanupTask(function () { - if (server.server) { - server.server.destroy(); - } - if (ui.servers) { - Object.keys(ui.servers).forEach(function (key) { - if (ui.servers[key].server) { - ui.servers[key].server.destroy(); - } - }); - } - }); - - done(null, { - instance: { - server: server.server.listen(port), - app: server.app - } - }); - - }, - /** - * Allow an API for adding/removing elements to clients - * @param ui - * @param done - */ - addElementEvents: function (ui, done) { - - var elems = ui.pluginManager.hook("elements"); - var bs = ui.bs; - - if (!Object.keys(elems).length) { - return done(); - } - - ui.setOption("clientFiles", Immutable.fromJS(elems)); - - done(null, { - instance: { - enableElement: require("./client-elements").enable(ui.clients, ui, bs), - disableElement: require("./client-elements").disable(ui.clients, ui, bs), - addElement: require("./client-elements").addElement - } - }); - }, - /** - * Run default plugins - * @param ui - * @param done - */ - registerPlugins: function (ui, done) { - Object.keys(ui.defaultPlugins).forEach(function (key) { - ui.pluginManager.get(key)(ui, ui.bs); - }); - done(); - }, - /** - * The most important event is the initial connection where - * the options are received from the socket - * @param ui - * @param done - */ - addOptionsEvent: function (ui, done) { - - var bs = ui.bs; - - ui.clients.on("connection", function (client) { - - client.emit("ui:connection", ui.options.toJS()); - - ui.options.get("clientFiles").map(function (item) { - if (item.get("active")) { - ui.addElement(client, item.toJS()); - } - }); - }); - - ui.socket.on("connection", function (client) { - - client.emit("connection", bs.getOptions().toJS()); - - client.emit("ui:connection", ui.options.toJS()); - - client.on("ui:get:options", function () { - client.emit("ui:receive:options", { - bs: bs.getOptions().toJS(), - ui: ui.options.toJS() - }); - }); - - // proxy client events - client.on("ui:client:proxy", function (evt) { - ui.clients.emit(evt.event, evt.data); - }); - - client.on("ui", function (data) { - ui.delegateEvent(data); - }); - }); - done(); - } -}; diff --git a/web/node_modules/browser-sync-ui/lib/client-elements.js b/web/node_modules/browser-sync-ui/lib/client-elements.js deleted file mode 100644 index 6c8b615..0000000 --- a/web/node_modules/browser-sync-ui/lib/client-elements.js +++ /dev/null @@ -1,94 +0,0 @@ -var fs = require("fs"); - -const CLIENT_FILES_OPT = "clientFiles"; - -/** - * Enable a element on clients - * @param clients - * @param ui - * @param bs - * @returns {Function} - */ - -var types = { - "css": "text/css", - "js": "application/javascript" -}; - -function enableElement (clients, ui, bs) { - - return function (file) { - - var uiItem = ui.getOptionIn([CLIENT_FILES_OPT, file.name]); - var item = uiItem.toJS(); - var enableFn = uiItem.getIn(["callbacks", "enable"]); - - if (item.active) { - return; - } - - ui.setOptionIn([CLIENT_FILES_OPT, item.name, "active"], true, {silent: true}); - - if (enableFn) { - enableFn.call(ui, item); - } - - if (item.file && !item.served) { - - ui.setOptionIn([CLIENT_FILES_OPT, item.name, "served"], true, {silent: true}); - - bs.serveFile(item.src, { - type: types[item.type], - content: fs.readFileSync(item.file) - }); - } - - addElement(clients, ui.getOptionIn([CLIENT_FILES_OPT, item.name]).toJS()); - }; -} - -/** - * @param clients - * @param ui - * @returns {Function} - */ -function disableElement (clients, ui) { - - return function (file) { - var uiItem = ui.getOptionIn([CLIENT_FILES_OPT, file.name]); - var item = uiItem.toJS(); - var disableFn = uiItem.getIn(["callbacks", "disable"]); - - if (disableFn) { - disableFn.call(ui, item); - } - - ui.setOptionIn([CLIENT_FILES_OPT, item.name, "active"], false, {silent: true}); - - removeElement(clients, item.id); - }; -} - -/** - * @param clients - * @param item - */ -function addElement (clients, item) { - - clients.emit("ui:element:add", item); -} - -/** - * @param clients - * @param id - */ -function removeElement(clients, id) { - - clients.emit("ui:element:remove", {id: id}); -} - -module.exports.addElement = addElement; -module.exports.removeElement = removeElement; -module.exports.enable = enableElement; -module.exports.disable = disableElement; - diff --git a/web/node_modules/browser-sync-ui/lib/client-js.js b/web/node_modules/browser-sync-ui/lib/client-js.js deleted file mode 100644 index 999b08c..0000000 --- a/web/node_modules/browser-sync-ui/lib/client-js.js +++ /dev/null @@ -1,120 +0,0 @@ -"use strict"; - -(function (window, document, bs, undefined) { - - var socket = bs.socket; - - var uiOptions = { - bs: {} - }; - - socket.on("ui:connection", function (options) { - - uiOptions = options; - - bs.socket.emit("ui:history:connected", { - href: window.location.href - }); - }); - - socket.on("ui:element:remove", function (data) { - if (data.id) { - var elem = document.getElementById(data.id); - if (elem) { - removeElement(elem); - } - } - }); - - socket.on("highlight", function () { - var id = "__browser-sync-highlight__"; - var elem = document.getElementById(id); - if (elem) { - return removeElement(elem); - } - (function (e) { - e.style.position = "fixed"; - e.style.zIndex = "1000"; - e.style.width = "100%"; - e.style.height = "100%"; - e.style.borderWidth = "5px"; - e.style.borderColor = "red"; - e.style.borderStyle = "solid"; - e.style.top = "0"; - e.style.left = "0"; - e.setAttribute("id", id); - document.getElementsByTagName("body")[0].appendChild(e); - })(document.createElement("div")); - }); - - socket.on("ui:element:add", function (data) { - - var elem = document.getElementById(data.id); - - if (!elem) { - if (data.type === "css") { - return addCss(data); - } - if (data.type === "js") { - return addJs(data); - } - if (data.type === "dom") { - return addDomNode(data); - } - } - }); - - bs.addDomNode = addDomNode; - bs.addJs = addJs; - bs.addCss = addJs; - - function addJs(data) { - (function (e) { - e.setAttribute("src", getAbsoluteUrl(data.src)); - e.setAttribute("id", data.id); - document.getElementsByTagName("body")[0].appendChild(e); - })(document.createElement("script")); - } - - function addCss(data) { - (function (e) { - e.setAttribute("rel", "stylesheet"); - e.setAttribute("type", "text/css"); - e.setAttribute("id", data.id); - e.setAttribute("media", "all"); - e.setAttribute("href", getAbsoluteUrl(data.src)); - document.getElementsByTagName("head")[0].appendChild(e); - })(document.createElement("link")); - } - - function addDomNode(data) { - var elem = document.createElement(data.tagName); - for (var attr in data.attrs) { - elem.setAttribute(attr, data.attrs[attr]); - } - if (data.placement) { - document.getElementsByTagName(data.placement)[0].appendChild(elem); - } else { - document.getElementsByTagName("body")[0].appendChild(elem); - } - return elem; - } - - function removeElement(element) { - if (element && element.parentNode) { - element.parentNode.removeChild(element); - } - } - - function getAbsoluteUrl(path) { - if (path.match(/^h/)) { - return path; - } - return [window.location.protocol, "//", getHost(), path].join(""); - } - - function getHost () { - return uiOptions.bs.mode === "snippet" ? window.location.hostname + ":" + uiOptions.bs.port : window.location.host; - } - -})(window, document, ___browserSync___); \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/config.js b/web/node_modules/browser-sync-ui/lib/config.js deleted file mode 100644 index 46dde67..0000000 --- a/web/node_modules/browser-sync-ui/lib/config.js +++ /dev/null @@ -1,40 +0,0 @@ -var Immutable = require("immutable"); - -/** - * Any configurable paths/config - * @type {{pluginName: string, indexPage: string, socketJs: string, appJs: string, connector: string}} - */ -var defaults = { - pluginName: "UI", - indexPage: "/index.html", - socketJs: "/js/vendor/socket.js", - appJs: "/js/dist/app.js", - app: "/app.js", - appExtraJs: "/js/app-extra.js", - connector: "/js/connector.js", - pagesConfig: "/js/pages-config.js", - public: { - svg: "/img/icons/icons.svg", - css: "/css/core.min.css" - }, - clientJs: "/lib/client-js.js", - socket: { - namespace: "/browser-sync-cp" - }, - components: { - header: "/components/header.html", - footer: "/components/footer.html" - } -}; - -module.exports.defaults = defaults; - -/** - * @param [userConfig] - * @returns {Map} - */ -module.exports.merge = function (userConfig) { - return Immutable - .fromJS(defaults) - .mergeDeep(userConfig); -}; \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/directive-stripper.js b/web/node_modules/browser-sync-ui/lib/directive-stripper.js deleted file mode 100644 index 72e4fe3..0000000 --- a/web/node_modules/browser-sync-ui/lib/directive-stripper.js +++ /dev/null @@ -1,86 +0,0 @@ -var tokenize = require("html-tokenize"); -var through2 = require("through2"); -var vinyl = require("vinyl"); -var select = require("html-select"); - -/** - * @param config - * @param item - * @param markup - * @param done - */ -function directiveStripper(config, item, markup, done) { - - var replacer = getReplacer(item, config); - var chunks = []; - - new vinyl({ - contents: new Buffer(markup) - }) - .pipe(tokenize()) - .pipe(replacer) - .pipe(through2.obj(function (row, buf, next) { - chunks.push(row[1]); - next(); - }, function () { - done(null, chunks.join("")); - })); - - replacer.resume(); -} - -/** - * @param name - * @param item - * @returns {*|exports} - */ -function getReplacer (name, markup) { - - return select(name, function (e) { - - var tr = through2.obj(function (row, buf, next) { - - if (row[0] === "open") { - this.push([row[0], directive(name, String(row[1]), markup)]); - } else { - this.push([ row[0], "" ]); - } - - next(); - }); - - tr.pipe(e.createStream()).pipe(tr); - }); -} - -/** - * @param name - * @param content - * @param item - * @returns {*|string} - */ -function directive (name, content, item) { - - var angularDir; - try { - angularDir = require("../src/scripts/directives/" + name)(); - } catch (e) { - console.log("Directive not found, cannot re-use"); - return content; - } - - var scope = item; - - scope = angularDir.link(scope, {}, {}); - - return angularDir.template.replace(/\{\{(.+?)\}\}/, function ($1, $2) { - if ($2 in scope) { - return scope[$2]; - } - return $1; - }); -} - -module.exports.getReplacer = getReplacer; -module.exports.directive = directive; -module.exports.directiveStripper = directiveStripper; \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/hooks.js b/web/node_modules/browser-sync-ui/lib/hooks.js deleted file mode 100644 index 4cd8549..0000000 --- a/web/node_modules/browser-sync-ui/lib/hooks.js +++ /dev/null @@ -1,271 +0,0 @@ -var fs = require("fs"); -var path = require("path"); - -var pluginTmpl = templateFile("/plugin.tmpl"); -var configTmpl = templateFile("/config.tmpl"); -var configItem = templateFile("/config.item.tmpl"); -var inlineTemp = templateFile("/inline.template.tmpl"); -var pluginItemTmpl = fs.readFileSync(path.resolve(__dirname, "../", "templates/plugin.item.tmpl"), "utf-8"); - -function templateFile (filepath) { - return fs.readFileSync(path.join(__dirname, "/../templates", filepath || ""), "utf-8"); -} - -/** - * @type {{page: Function, markup: Function, client:js: Function, templates: Function}} - */ -module.exports = { - /** - * Create the url config for each section of the ui - * @param hooks - * @param ui - */ - "page": function (hooks, ui) { - - var config = hooks - .map(transformConfig) - .reduce(createConfigItem, {}); - - return { - /** - * pagesConfig - This is the angular configuration such as routes - */ - pagesConfig: configTmpl - .replace("%when%", hooks.reduce( - createAngularRoutes, - "" - )) - .replace("%pages%", JSON.stringify( - config, - null, - 4 - )), - /** - * pagesConfig in object form - */ - pagesObj: config, - pageMarkup: function () { - return preAngular(ui.pluginManager.plugins, config, ui); - } - }; - }, - /** - * Controller markup for each plugin - * @param hooks - * @returns {*} - */ - "markup": function (hooks) { - return hooks.reduce(pluginTemplate, ""); - }, - /** - * @param hooks - * @param {UI} ui - * @returns {*|string} - */ - "client:js": function (hooks, ui) { - - /** - * Add client JS from Browsersync Plugins - */ - ui.bsPlugins.forEach(function (plugin) { - if (plugin.has("client:js")) { - plugin.get("client:js").forEach(function (value) { - hooks.push(value); - }); - } - }); - - var out = hooks.reduce(function (all, item) { - if (typeof item === "string") { - all += ";" + item; - } else if (Array.isArray(item)) { - item.forEach(function (item) { - all += ";" + item; - }); - } - return all; - }, ""); - - return out; - }, - /** - * @param hooks - * @param initial - * @param {UI} ui - * @returns {String} - */ - "templates": function (hooks, initial, ui) { - - /** - * Add templates from each Browsersync registered plugin - * @type {string} - */ - var pluginDirectives = ui.bsPlugins.reduce(function (all, plugin) { - - if (!plugin.has("templates")) { - return all; - } - - /** - * Slugify-ish the plugin name - * eg: Test Browsersync Plugin - * = test-browsersync-plugin - * @type {string} - */ - var slug = plugin.get("name") - .trim() - .split(" ") - .map(function (word) { - return word.trim().toLowerCase(); - }) - .join("-"); - - /** - * For every plugin that has templates, wrap - * the markup in the - * markup to result in the single output string. - */ - plugin.get("templates").forEach(function (value, key) { - all += angularWrap([slug, path.basename(key)].join("/"), value); - }); - - return all; - - }, ""); - - /** - * Combine the markup from the plugins done above with any - * others registered via hooks + initial - * to create the final markup - */ - return [pluginDirectives, createInlineTemplates(hooks.concat([initial]))].join(""); - }, - /** - * Allow plugins to register toggle-able elements - * @param hooks - * @returns {{}} - */ - "elements": function (hooks) { - var obj = {}; - hooks.forEach(function (elements) { - elements.forEach(function (item) { - if (!obj[item.name]) { - obj[item.name] = item; - } - }); - }); - return obj; - } -}; - -/** - * @param hooks - * @returns {String} - */ -function createInlineTemplates (hooks) { - return hooks.reduce(function (combined, item) { - return combined + item.reduce(function (all, filepath) { - return all + angularWrap( - path.basename(filepath), - fs.readFileSync(filepath)); - }, ""); - }, ""); -} - -/** - * @param item - * @returns {*} - */ -function transformConfig (item) { - return item; -} - -/** - * @param {String} all - * @param {Object} item - * @returns {*} - */ -function createAngularRoutes(all, item) { - return all + configItem.replace(/%(.+)%/g, function () { - var key = arguments[1]; - if (item[key]) { - return item[key]; - } - }); -} - -/** - * @param joined - * @param item - * @returns {*} - */ -function createConfigItem (joined, item) { - if (item.path === "/") { - joined["overview"] = item; - } else { - joined[item.path.slice(1)] = item; - } - return joined; -} - -/** - * @returns {*} - */ -function pluginTemplate (combined, item) { - return [combined, pluginTmpl.replace("%markup%", item)].join("\n"); -} - -/** - * @param plugins - * @param config - * @returns {*} - */ -function preAngular (plugins, config, ui) { - - return Object.keys(plugins) - .filter(function (key) { - return config[key]; // only work on plugins that have pages - }) - .map(function (key) { - if (key === "plugins") { - var pluginMarkup = ui.bsPlugins.reduce(function (all, item, i) { - all += pluginItemTmpl - .replace("%content%", item.get("markup") || "") - .replace(/%index%/g, i) - .replace(/%name%/g, item.get("name")); - - return all; - }, ""); - plugins[key].hooks.markup = plugins[key].hooks.markup.replace("%pluginlist%", pluginMarkup); - } - return angularWrap(config[key].template, bindOnce(plugins[key].hooks.markup, config[key])); - }) - .reduce(function (combined, item) { - return combined + item; - }, ""); -} - -/** - * @param templateName - * @param markup - * @returns {*} - */ -function angularWrap (templateName, markup) { - return inlineTemp - .replace("%content%", markup) - .replace("%id%", templateName); -} - -/** - * @param markup - * @param config - * @returns {*|string} - */ -function bindOnce (markup, config) { - return markup.toString().replace(/\{\{ctrl.section\.(.+?)\}\}/g, function ($1, $2) { - return config[$2] || ""; - }); -} - -module.exports.bindOnce = bindOnce; - diff --git a/web/node_modules/browser-sync-ui/lib/opts.js b/web/node_modules/browser-sync-ui/lib/opts.js deleted file mode 100644 index 9cf2a60..0000000 --- a/web/node_modules/browser-sync-ui/lib/opts.js +++ /dev/null @@ -1,31 +0,0 @@ -var Immutable = require("immutable"); - -var defaults = Immutable.fromJS({ - port: 3001, - weinre: { - port: 8080 - } -}); - -/** - * @param {Object} obj - * @returns {Map} - */ -module.exports.merge = function (obj) { - return defaults.mergeDeep(Immutable.fromJS(obj)); -}; - -/** - * @param {Immutable.Map} obj - * @returns {*} - */ -//function transformOptions(obj) { -// -// var out; -// -// Object.keys(transforms).forEach(function (key) { -// out = obj.set(key, transforms[key](obj)); -// }); -// -// return out; -//} \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/connections/connections.client.js b/web/node_modules/browser-sync-ui/lib/plugins/connections/connections.client.js deleted file mode 100644 index 65bc7a8..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/connections/connections.client.js +++ /dev/null @@ -1,69 +0,0 @@ -(function (angular) { - - const SECTION_NAME = "connections"; - - angular - .module("BrowserSync") - .controller("ConnectionsController", [ - "pagesConfig", - ConnectionsControllers - ]); - - /** - * @param pagesConfig - * @constructor - */ - function ConnectionsControllers(pagesConfig) { - var ctrl = this; - ctrl.section = pagesConfig[SECTION_NAME]; - } - - angular - .module("BrowserSync") - .directive("connectionList", function () { - return { - restrict: "E", - scope: { - options: "=" - }, - templateUrl: "connections.directive.html", - controller: ["$scope", "Clients", "Socket", connectionListDirective], - controllerAs: "ctrl" - }; - }); - - /** - * Controller for the URL sync - * @param $scope - directive scope - * @param Clients - * @param Socket - */ - function connectionListDirective($scope, Clients, Socket) { - - var ctrl = this; - ctrl.connections = []; - - ctrl.update = function (data) { - ctrl.connections = data; - $scope.$digest(); - }; - - // Always try to retreive the sockets first time. - Socket.getData("clients").then(function (data) { - ctrl.connections = data; - }); - - // Listen to events to update the list on the fly - Socket.on("ui:connections:update", ctrl.update); - - $scope.$on("$destroy", function () { - Socket.off("ui:connections:update", ctrl.update); - }); - - ctrl.highlight = function (connection) { - Clients.highlight(connection); - }; - } - -})(angular); - diff --git a/web/node_modules/browser-sync-ui/lib/plugins/connections/connections.directive.html b/web/node_modules/browser-sync-ui/lib/plugins/connections/connections.directive.html deleted file mode 100644 index 776d99b..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/connections/connections.directive.html +++ /dev/null @@ -1,10 +0,0 @@ -
    -
  • -

    {{connection.browser.name}} - ({{connection.browser.version}})

    - -
  • -
\ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/connections/connections.html b/web/node_modules/browser-sync-ui/lib/plugins/connections/connections.html deleted file mode 100644 index b16ec2c..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/connections/connections.html +++ /dev/null @@ -1,18 +0,0 @@ -
-

{{section.title}}

-
-
-
-

Connected devices/browsers will be listed here. If you are not seeing your device in the list, - it's probably because the Browsersync script tag is not being loaded on your page.

-

- Browsersync works by injecting an asynchronous script tag (<script async>...</script>) right after the <body> tag during initial request. In order for this to work properly the <body> tag must be present. Alternatively you can provide a custom rule for the snippet using snippetOptions -

-
-
- -
- -
diff --git a/web/node_modules/browser-sync-ui/lib/plugins/connections/connections.plugin.js b/web/node_modules/browser-sync-ui/lib/plugins/connections/connections.plugin.js deleted file mode 100644 index a6ebd0f..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/connections/connections.plugin.js +++ /dev/null @@ -1,45 +0,0 @@ -var connections = require("./lib/connections"); - -const PLUGIN_NAME = "Connections"; - -/** - * @type {{plugin: Function, plugin:name: string, markup: string}} - */ -module.exports = { - /** - * @param {UI} ui - * @param {BrowserSync} bs - */ - "plugin": function (ui, bs) { - connections.init(ui, bs); - }, - /** - * Hooks - */ - "hooks": { - "client:js": fileContent("/connections.client.js"), - "templates": [ - getPath("/connections.directive.html") - ] - }, - /** - * Plugin name - */ - "plugin:name": PLUGIN_NAME -}; - -/** - * @param filepath - * @returns {*} - */ -function getPath (filepath) { - return require("path").join(__dirname, filepath); -} - -/** - * @param filepath - * @returns {*} - */ -function fileContent (filepath) { - return require("fs").readFileSync(getPath(filepath), "utf-8"); -} \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/connections/lib/connections.js b/web/node_modules/browser-sync-ui/lib/plugins/connections/lib/connections.js deleted file mode 100644 index 68baeeb..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/connections/lib/connections.js +++ /dev/null @@ -1,132 +0,0 @@ -var Immutable = require("immutable"); - -/** - * Track connected clients - * @param {UI} ui - * @param {BrowserSync} bs - */ -module.exports.init = function (ui, bs) { - - var uaParser = new bs.utils.UAParser(); - - var currentConnections = []; - - ui.clients.on("connection", function (client) { - client.on("client:heartbeat", function (data) { - var match; - if (currentConnections.some(function (item, index) { - if (item.id === client.id) { - match = index; - return true; - } - return false; - })) { - if (typeof match === "number") { - currentConnections[match].timestamp = new Date().getTime(); - currentConnections[match].data = data; - } - } else { - currentConnections.push({ - id: client.id, - timestamp: new Date().getTime(), - browser: uaParser.setUA(client.handshake.headers["user-agent"]).getBrowser(), - data: data - }); - } - }); - }); - - var registry; - var temp; - var initialSent; - - var int = setInterval(function () { - - var sockets = ui.clients.sockets; - var keys = Object.keys(sockets); - - if (keys.length) { - temp = Immutable.List(keys.map(function (clientKey) { - var currentClient = sockets[clientKey]; - return Immutable.fromJS({ - id: currentClient.id, - browser: uaParser.setUA(currentClient.handshake.headers["user-agent"]).getBrowser() - }); - })); - if (!registry) { - registry = temp; - sendUpdated(ui.socket, decorateClients(registry.toJS(), currentConnections)); - } else { - if (Immutable.is(registry, temp)) { - if (!initialSent) { - sendUpdated(ui.socket, decorateClients(registry.toJS(), currentConnections)); - initialSent = true; - } - } else { - registry = temp; - sendUpdated(ui.socket, decorateClients(registry.toJS(), currentConnections)); - } - } - } else { - sendUpdated(ui.socket, []); - } - - }, 1000); - - bs.registerCleanupTask(function () { - clearInterval(int); - }); -}; - - -/** - * Use heart-beated data to decorate clients - * @param clients - * @param clientsInfo - * @returns {*} - */ -function decorateClients(clients, clientsInfo) { - return clients.map(function (item) { - clientsInfo.forEach(function (client) { - if (client.id === item.id) { - item.data = client.data; - return false; - } - }); - return item; - }); -} - -/** - * @param socket - * @param connectedClients - */ -function sendUpdated(socket, connectedClients) { - socket.emit("ui:connections:update", connectedClients); -} - -/** - * @param clients - * @param data - */ -//function highlightClient (clients, data) { -// var socket = getClientById(clients, data.id); -// if (socket) { -// socket.emit("highlight"); -// } -//} - -/** - * @param clients - * @param id - */ -//function getClientById (clients, id) { -// var match; -// clients.sockets.some(function (item, i) { -// if (item.id === id) { -// match = clients.sockets[i]; -// return true; -// } -// }); -// return match; -//} \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/help/help.client.js b/web/node_modules/browser-sync-ui/lib/plugins/help/help.client.js deleted file mode 100644 index 27e5e0c..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/help/help.client.js +++ /dev/null @@ -1,24 +0,0 @@ -(function (angular) { - - const SECTION_NAME = "history"; - - angular - .module("BrowserSync") - .controller("HelpAboutController", [ - "options", - "pagesConfig", - helpAboutController - ]); - - /** - * @param options - * @param pagesConfig - */ - function helpAboutController(options, pagesConfig) { - var ctrl = this; - ctrl.options = options.bs; - ctrl.section = pagesConfig[SECTION_NAME]; - } - -})(angular); - diff --git a/web/node_modules/browser-sync-ui/lib/plugins/help/help.directive.html b/web/node_modules/browser-sync-ui/lib/plugins/help/help.directive.html deleted file mode 100644 index e69de29..0000000 diff --git a/web/node_modules/browser-sync-ui/lib/plugins/help/help.html b/web/node_modules/browser-sync-ui/lib/plugins/help/help.html deleted file mode 100644 index 387afa3..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/help/help.html +++ /dev/null @@ -1,8 +0,0 @@ -
-

{{ctrl.section.title}}

-
-
-
-

Help page

-
-
\ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/help/help.plugin.js b/web/node_modules/browser-sync-ui/lib/plugins/help/help.plugin.js deleted file mode 100644 index 5467c34..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/help/help.plugin.js +++ /dev/null @@ -1,49 +0,0 @@ -const PLUGIN_NAME = "Help / About"; - -/** - * @type {{plugin: Function, plugin:name: string, markup: string}} - */ -module.exports = { - /** - * Plugin init - */ - "plugin": function () {}, - /** - * Hooks - */ - "hooks": { - "markup": fileContent("/../../../static/content/help.content.html"), - "client:js": fileContent("/help.client.js"), - "templates": [ - getPath("/help.directive.html") - ], - "page": { - path: "/help", - title: PLUGIN_NAME, - template: "help.html", - controller: "HelpAboutController", - order: 6, - icon: "help" - } - }, - /** - * Plugin name - */ - "plugin:name": PLUGIN_NAME -}; - -/** - * @param filepath - * @returns {*} - */ -function getPath (filepath) { - return require("path").join(__dirname, filepath); -} - -/** - * @param filepath - * @returns {*} - */ -function fileContent (filepath) { - return require("fs").readFileSync(getPath(filepath), "utf-8"); -} \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/history/history.client.js b/web/node_modules/browser-sync-ui/lib/plugins/history/history.client.js deleted file mode 100644 index 0a1d043..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/history/history.client.js +++ /dev/null @@ -1,111 +0,0 @@ -(function (angular) { - - const SECTION_NAME = "history"; - - angular - .module("BrowserSync") - .controller("HistoryController", [ - "$scope", - "options", - "History", - "pagesConfig", - historyController - ]); - - /** - * @param $scope - * @param options - * @param History - * @param pagesConfig - */ - function historyController($scope, options, History, pagesConfig) { - - var ctrl = this; - ctrl.options = options.bs; - ctrl.section = pagesConfig[SECTION_NAME]; - ctrl.visited = []; - - ctrl.update = function (items) { - ctrl.visited = items; - $scope.$digest(); - }; - - History.get().then(function (items) { - ctrl.visited = items; - }); - - History.on("change", ctrl.update); - - $scope.$on("$destroy", function () { - History.off(ctrl.update); - }); - - ctrl.clearVisited = function () { - History.clear(); - }; - } - - angular - .module("BrowserSync") - .directive("historyList", function () { - return { - restrict: "E", - scope: { - options: "=", - visited: "=" - }, - templateUrl: "history.directive.html", - controller: ["$scope", "History", "Clients", historyDirective], - controllerAs: "ctrl" - }; - }); - - /** - * Controller for the URL sync - * @param $scope - directive scope - * @param History - * @param Clients - */ - function historyDirective($scope, History, Clients) { - - var ctrl = this; - - ctrl.visited = []; - - ctrl.utils = {}; - - ctrl.utils.localUrl = function (path) { - return [$scope.options.urls.local, path].join(""); - }; - - ctrl.updateVisited = function (data) { - ctrl.visited = data; - $scope.$digest(); - }; - - ctrl.sendAllTo = function (url) { - url.success = true; - Clients.sendAllTo(url.path); - setTimeout(function () { - url.success = false; - $scope.$digest(); - }, 1000); - }; - - ctrl.removeVisited = function (item) { - History.remove(item); - }; - - History.get().then(function (items) { - ctrl.visited = items; - }); - - History.on("change", ctrl.updateVisited); - - $scope.$on("$destroy", function () { - History.off(ctrl.updateVisited); - }); - } - -})(angular); - diff --git a/web/node_modules/browser-sync-ui/lib/plugins/history/history.directive.html b/web/node_modules/browser-sync-ui/lib/plugins/history/history.directive.html deleted file mode 100644 index ad72102..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/history/history.directive.html +++ /dev/null @@ -1,20 +0,0 @@ -
\ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/history/history.html b/web/node_modules/browser-sync-ui/lib/plugins/history/history.html deleted file mode 100644 index 8e181d4..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/history/history.html +++ /dev/null @@ -1,16 +0,0 @@ -
-

{{ctrl.section.title}}

-
-
- -
-
-
-

Pages you navigate to will appear here - making it easy - to sync all devices to a specific page

-
-
- \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/history/history.js b/web/node_modules/browser-sync-ui/lib/plugins/history/history.js deleted file mode 100644 index ed489c6..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/history/history.js +++ /dev/null @@ -1,132 +0,0 @@ -var url = require("url"); -var Immutable = require("immutable"); - -module.exports.init = function (ui, bs) { - - var validUrls = Immutable.OrderedSet(); - - var methods = { - /** - * Send the url list to UI - * @param urls - */ - sendUpdatedUrls: function (urls) { - ui.socket.emit("ui:history:update", decorateUrls(urls)); - }, - /** - * Only send to UI if list changed - * @param current - * @param temp - */ - sendUpdatedIfChanged: function (current, temp) { - if (!Immutable.is(current, temp)) { - validUrls = temp; - methods.sendUpdatedUrls(validUrls); - } - }, - /** - * Send all clients to a URL - this is a proxy - * in case we need to limit/check anything. - * @param data - */ - sendToUrl: function (data) { - - var parsed = url.parse(data.path); - - data.override = true; - data.path = parsed.path; - data.url = parsed.href; - - ui.clients.emit("browser:location", data); - }, - /** - * Add a new path - * @param data - */ - addPath: function (data) { - var temp = addPath(validUrls, url.parse(data.href), bs.options.get("mode")); - methods.sendUpdatedIfChanged(validUrls, temp, ui.socket); - }, - /** - * Remove a path - * @param data - */ - removePath: function (data) { - var temp = removePath(validUrls, data.path); - methods.sendUpdatedIfChanged(validUrls, temp, ui.socket); - }, - /** - * Get the current list - */ - getVisited: function () { - ui.socket.emit("ui:receive:visited", decorateUrls(validUrls)); - } - }; - - ui.clients.on("connection", function (client) { - client.on("ui:history:connected", methods.addPath); - }); - - ui.socket.on("connection", function (uiClient) { - /** - * Send urls on first connection - */ - uiClient.on("ui:get:visited", methods.getVisited); - methods.sendUpdatedUrls(validUrls); - }); - - ui.listen("history", { - "sendAllTo": methods.sendToUrl, - "remove": methods.removePath, - "clear": function () { - validUrls = Immutable.OrderedSet([]); - methods.sendUpdatedUrls(validUrls); - } - }); - - return methods; -}; - -/** - * @param {Immutable.Set} urls - * @returns {Array} - */ -function decorateUrls (urls) { - var count = 0; - return urls.map(function (value) { - count += 1; - return { - path: value, - key: count - }; - }).toJS().reverse(); -} - -/** - * If snippet mode, add the full URL - * if server/proxy, add JUST the path - * @param immSet - * @param urlObj - * @param mode - * @returns {Set} - */ -function addPath(immSet, urlObj, mode) { - return immSet.add( - mode === "snippet" - ? urlObj.href - : urlObj.path - ); -} - -module.exports.addPath = addPath; - -/** - * @param immSet - * @param urlPath - * @returns {*} - */ -function removePath(immSet, urlPath) { - return immSet.remove(url.parse(urlPath).path); -} - -module.exports.removePath = removePath; diff --git a/web/node_modules/browser-sync-ui/lib/plugins/history/history.plugin.js b/web/node_modules/browser-sync-ui/lib/plugins/history/history.plugin.js deleted file mode 100644 index 2a2a52b..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/history/history.plugin.js +++ /dev/null @@ -1,54 +0,0 @@ -var historyPlugin = require("./history"); - -const PLUGIN_NAME = "History"; - -/** - * @type {{plugin: Function, plugin:name: string, markup: string}} - */ -module.exports = { - /** - * @param ui - * @param bs - */ - "plugin": function (ui, bs) { - ui.history = historyPlugin.init(ui, bs); - }, - /** - * Hooks - */ - "hooks": { - "markup": fileContent("history.html"), - "client:js": fileContent("/history.client.js"), - "templates": [ - getPath("/history.directive.html") - ], - "page": { - path: "/history", - title: PLUGIN_NAME, - template: "history.html", - controller: PLUGIN_NAME + "Controller", - order: 3, - icon: "list2" - } - }, - /** - * Plugin name - */ - "plugin:name": PLUGIN_NAME -}; - -/** - * @param filepath - * @returns {*} - */ -function getPath (filepath) { - return require("path").join(__dirname, filepath); -} - -/** - * @param filepath - * @returns {*} - */ -function fileContent (filepath) { - return require("fs").readFileSync(getPath(filepath), "utf-8"); -} \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/network-throttle.client.js b/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/network-throttle.client.js deleted file mode 100644 index de1df97..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/network-throttle.client.js +++ /dev/null @@ -1,201 +0,0 @@ -(function (angular) { - - const SECTION_NAME = "network-throttle"; - - angular - .module("BrowserSync") - .controller("NetworkThrottleController", [ - "options", - "pagesConfig", - "Socket", - "$scope", - NetworkThrottleController - ]); - - /** - * @param options - * @param pagesConfig - * @param Socket - * @param $scope - */ - function NetworkThrottleController (options, pagesConfig, Socket, $scope) { - - var ctrl = this; - - ctrl.section = pagesConfig[SECTION_NAME]; - ctrl.options = options.bs; - ctrl.uiOptions = options.ui; - ctrl.clientFiles = options.ui.clientFiles || {}; - ctrl.section = pagesConfig[SECTION_NAME]; - - ctrl.throttle = ctrl.uiOptions[SECTION_NAME]; - ctrl.selected = ctrl.throttle.targets[0].id; - ctrl.servers = ctrl.throttle.servers; - ctrl.port = ""; - ctrl.portEntry = "auto"; - ctrl.serverCount = Object.keys(ctrl.servers).length; - ctrl.blurs = []; - - ctrl.state = { - success: false, - waiting: false, - classname: "ready" - }; - - ctrl.createServer = function (selected, event) { - - if (ctrl.blurs.indexOf(event.target) === -1) { - ctrl.blurs.push(event.target); - } - - var item = getByProp(ctrl.throttle.targets, "id", ctrl.selected); - - - if (ctrl.portEntry === "auto") { - return send(""); - } - - if (!ctrl.port || !ctrl.port.length) { - setError(); - return; - } - - if (!ctrl.port.match(/\d{4,5}/)) { - setError(); - return; - } - - var port = parseInt(ctrl.port, 10); - - if (port < 1024 || port > 65535) { - setError(); - return; - } - - send(ctrl.port); - - function setError() { - ctrl.state.waiting = false; - ctrl.state.portError = true; - } - - function send (port) { - - ctrl.state.classname = "waiting"; - ctrl.state.waiting = true; - - Socket.uiEvent({ - namespace: SECTION_NAME, - event: "server:create", - data: { - speed: item, - port: port - } - }); - } - }; - - ctrl.destroyServer = function (item, port) { - Socket.uiEvent({ - namespace: SECTION_NAME, - event: "server:destroy", - data: { - speed: item, - port: port - } - }); - }; - - ctrl.toggleSpeed = function (item) { - if (!item.active) { - item.urls = []; - } - }; - - ctrl.update = function (data) { - - ctrl.servers = data.servers; - ctrl.serverCount = Object.keys(ctrl.servers).length; - - if (data.event === "server:create") { - updateButtonState(); - } - - $scope.$digest(); - }; - - function updateButtonState() { - - ctrl.state.success = true; - ctrl.state.classname = "success"; - - setTimeout(function () { - - ctrl.blurs.forEach(function (elem) { - elem.blur(); - }); - - setTimeout(function () { - ctrl.state.success = false; - ctrl.state.waiting = false; - ctrl.state.classname = "ready"; - - $scope.$digest(); - - }, 500); - - }, 300); - } - - /** - * @param collection - * @param prop - * @returns {*} - */ - function getByProp (collection, prop, name) { - var match = collection.filter(function (item) { - return item[prop] === name; - }); - if (match.length) { - return match[0]; - } - return false; - } - - Socket.on("ui:network-throttle:update", ctrl.update); - $scope.$on("$destroy", function () { - Socket.off("ui:network-throttle:update", ctrl.update); - }); - } - - /** - * Display the snippet when in snippet mode - */ - angular - .module("BrowserSync") - .directive("throttle", function () { - return { - restrict: "E", - replace: true, - scope: { - "target": "=", - "options": "=" - }, - templateUrl: "network-throttle.directive.html", - controller: ["$scope", "Socket", throttleDirectiveControlller], - controllerAs: "ctrl" - }; - }); - - /** - * @param $scope - */ - function throttleDirectiveControlller ($scope) { - - var ctrl = this; - - ctrl.throttle = $scope.options[SECTION_NAME]; - - } - -})(angular); \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/network-throttle.directive.html b/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/network-throttle.directive.html deleted file mode 100644 index 199aa6e..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/network-throttle.directive.html +++ /dev/null @@ -1,12 +0,0 @@ -
-
-

- Creating a throttled server, please wait... -

-
- -
-
-
diff --git a/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/network-throttle.html b/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/network-throttle.html deleted file mode 100644 index 4ad0d2f..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/network-throttle.html +++ /dev/null @@ -1,93 +0,0 @@ -
-
-

- - {{ctrl.section.title}} -

-
-
-
-

Sorry, Network Throttling is only available in Server or Proxy mode.

-
-
-
-
-
-
-

Speed

-
- - - -
-
-
-

Port

-
-
- - -
-
- - -
- - -
-
-
- -
- - -
-
-
-
-
-
-
-
-
-

Your Servers:

-

Your Servers will appear here...

-
- - -
- -
diff --git a/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/network-throttle.js b/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/network-throttle.js deleted file mode 100644 index 7d748ee..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/network-throttle.js +++ /dev/null @@ -1,159 +0,0 @@ -var Immutable = require("immutable"); - -module.exports.init = function (ui) { - - var optPath = ["network-throttle"]; - var serverOptPath = optPath.concat(["servers"]); - ui.servers = {}; - - ui.setOptionIn(optPath, Immutable.fromJS({ - name: "network-throttle", - title: "Network Throttle", - active: false, - targets: require("./targets") - })); - - ui.setOptionIn(serverOptPath, Immutable.Map({})); - - /** - * @param input - * @returns {number} - */ - function getPortArg(input) { - input = input.trim(); - if (input.length && input.match(/\d{3,5}/)) { - input = parseInt(input, 10); - } else { - input = ui.bs.options.get("port") + 1; - } - return input; - } - - /** - * @returns {string} - */ - function getTargetUrl() { - return require("url").parse(ui.bs.options.getIn(["urls", "local"])); - } - - var methods = { - /** - * @param data - */ - "server:create": function (data) { - - data.port = getPortArg(data.port); - data.cb = data.cb || function () { /* noop */}; - - /** - * @param opts - */ - function saveThrottleInfo (opts) { - - var urls = getUrls(ui.bs.options.set("port", opts.port).toJS()); - - ui.setOptionIn(serverOptPath.concat([opts.port]), Immutable.fromJS({ - urls: urls, - speed: opts.speed - })); - - setTimeout(function () { - - ui.socket.emit("ui:network-throttle:update", { - servers: ui.getOptionIn(serverOptPath).toJS(), - event: "server:create" - }); - - ui.servers[opts.port] = opts.server; - - data.cb(null, opts); - - }, 300); - - } - - /** - * @param err - * @param port - */ - function createThrottle (err, port) { - - var target = getTargetUrl(); - - var args = { - port: port, - target: target, - speed: data.speed - }; - - if (ui.bs.getOption("scheme") === "https") { - var httpsOpts = require("browser-sync/lib/server/utils").getHttpsOptions(ui.bs.options); - args.key = httpsOpts.key; - args.cert = httpsOpts.cert; - } - - args.server = require("./throttle-server")(args); - require('server-destroy')(args.server); - args.server.listen(port); - - saveThrottleInfo(args); - } - - /** - * Try for a free port - */ - ui.bs.utils.portscanner.findAPortNotInUse(data.port, data.port + 100, "127.0.0.1", function (err, port) { - if (err) { - return createThrottle(err); - } else { - createThrottle(null, port); - } - }); - }, - /** - * @param data - */ - "server:destroy": function (data) { - if (ui.servers[data.port]) { - ui.servers[data.port].destroy(); - ui.setMany(function (item) { - item.deleteIn(serverOptPath.concat([parseInt(data.port, 10)])); - }); - delete ui.servers[data.port]; - } - ui.socket.emit("ui:network-throttle:update", { - servers: ui.getOptionIn(serverOptPath).toJS(), - event: "server:destroy" - }); - }, - /** - * @param event - */ - event: function (event) { - methods[event.event](event.data); - } - }; - - return methods; -}; - -/** - * Get local + external urls with a different port - * @param opts - * @returns {List|List} - */ -function getUrls (opts) { - - var list = []; - - var bsLocal = require("url").parse(opts.urls.local); - - list.push([bsLocal.protocol + "//", bsLocal.hostname, ":", opts.port].join("")); - - if (opts.urls.external) { - var external = require("url").parse(opts.urls.external); - list.push([bsLocal.protocol + "//", external.hostname, ":", opts.port].join("")); - } - - return Immutable.List(list); -} diff --git a/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/network-throttle.plugin.js b/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/network-throttle.plugin.js deleted file mode 100644 index 989acd8..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/network-throttle.plugin.js +++ /dev/null @@ -1,53 +0,0 @@ -var networkThrottle = require("./network-throttle"); - -const PLUGIN_NAME = "Network Throttle"; - -/** - * @type {{plugin: Function, plugin:name: string, markup: string}} - */ -module.exports = { - /** - * Plugin init - */ - "plugin": function (ui, bs) { - ui.throttle = networkThrottle.init(ui, bs); - ui.listen("network-throttle", ui.throttle); - }, - - /** - * Hooks - */ - "hooks": { - "markup": fileContent("/network-throttle.html"), - "client:js": [fileContent("/network-throttle.client.js")], - "templates": [], - "page": { - path: "/network-throttle", - title: PLUGIN_NAME, - template: "network-throttle.html", - controller: "NetworkThrottleController", - order: 5, - icon: "time" - } - }, - /** - * Plugin name - */ - "plugin:name": PLUGIN_NAME -}; - -/** - * @param filepath - * @returns {*} - */ -function getPath (filepath) { - return require("path").join(__dirname, filepath); -} - -/** - * @param filepath - * @returns {*} - */ -function fileContent (filepath) { - return require("fs").readFileSync(getPath(filepath)); -} \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/targets.js b/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/targets.js deleted file mode 100644 index be20a72..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/targets.js +++ /dev/null @@ -1,57 +0,0 @@ -module.exports = [ - { - active: false, - title: "DSL (2Mbs, 5ms RTT)", - id: "dsl", - speed: 200, - latency: 5, - urls: [], - order: 1 - }, - { - active: false, - title: "4G (4Mbs, 20ms RTT)", - id: "4g", - speed: 400, - latency: 10, - urls: [], - order: 2 - - }, - { - active: false, - title: "3G (750kbs, 100ms RTT)", - id: "3g", - speed: 75, - latency: 50, - urls: [], - order: 3 - }, - { - active: false, - id: "good-2g", - title: "Good 2G (450kbs, 150ms RTT)", - speed: 45, - latency: 75, - urls: [], - order: 4 - }, - { - active: false, - id: "2g", - title: "Regular 2G (250kbs, 300ms RTT)", - speed: 25, - latency: 150, - urls: [], - order: 5 - }, - { - active: false, - id: "gprs", - title: "GPRS (50kbs, 500ms RTT)", - speed: 5, - latency: 250, - urls: [], - order: 6 - } -]; diff --git a/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/throttle-server.js b/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/throttle-server.js deleted file mode 100644 index e7d5e9f..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/network-throttle/throttle-server.js +++ /dev/null @@ -1,70 +0,0 @@ -var ThrottleGroup = require("stream-throttle").ThrottleGroup; - -module.exports = throttle; - -/** - * - */ -function throttle (opts) { - - var options = { - local_host: "localhost", - remote_host: "localhost", - upstream: 10*1024, - downstream: opts.speed.speed * 1024, - keepalive: false - }; - - var serverOpts = { - allowHalfOpen: true, - rejectUnauthorized: false - }; - - var module = "net"; - var method = "createConnection"; - - if (opts.key) { - module = "tls"; - method = "connect"; - serverOpts.key = opts.key; - serverOpts.cert = opts.cert; - } - - return require(module).createServer(serverOpts, function (local) { - - var remote = require(module)[method]({ - host: opts.target.hostname, - port: opts.target.port, - allowHalfOpen: true, - rejectUnauthorized: false - }); - - var upThrottle = new ThrottleGroup({ rate: options.upstream }); - var downThrottle = new ThrottleGroup({ rate: options.downstream }); - - var localThrottle = upThrottle.throttle(); - var remoteThrottle = downThrottle.throttle(); - - setTimeout(function () { - local - .pipe(localThrottle) - .pipe(remote); - }, opts.speed.latency); - - setTimeout(function () { - remote - .pipe(remoteThrottle) - .pipe(local); - }, opts.speed.latency); - - local.on("error", function() { - remote.destroy(); - local.destroy(); - }); - - remote.on("error", function() { - local.destroy(); - remote.destroy(); - }); - }); -} \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/overview/overview.client.js b/web/node_modules/browser-sync-ui/lib/plugins/overview/overview.client.js deleted file mode 100644 index cb78b52..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/overview/overview.client.js +++ /dev/null @@ -1,131 +0,0 @@ -(function (angular) { - - const SECTION_NAME = "overview"; - - angular - .module("BrowserSync") - .controller("OverviewController", [ - "options", - "pagesConfig", - OverviewController - ]); - - /** - * @param options - * @param pagesConfig - */ - function OverviewController (options, pagesConfig) { - var ctrl = this; - ctrl.section = pagesConfig[SECTION_NAME]; - ctrl.options = options.bs; - ctrl.ui = { - snippet: !ctrl.options.server && !ctrl.options.proxy - }; - } - - /** - * Url Info - this handles rendering of each server - * info item - */ - angular - .module("BrowserSync") - .directive("urlInfo", function () { - return { - restrict: "E", - replace: true, - scope: { - "options": "=" - }, - templateUrl: "url-info.html", - controller: [ - "$scope", - "$rootScope", - "Clients", - urlInfoController - ] - }; - }); - - /** - * @param $scope - * @param $rootScope - * @param Clients - */ - function urlInfoController($scope, $rootScope, Clients) { - - var options = $scope.options; - var urls = options.urls; - - $scope.ui = { - server: false, - proxy: false - }; - - if ($scope.options.mode === "server") { - $scope.ui.server = true; - if (!Array.isArray($scope.options.server.baseDir)) { - $scope.options.server.baseDir = [$scope.options.server.baseDir]; - } - } - - if ($scope.options.mode === "proxy") { - $scope.ui.proxy = true; - } - - $scope.urls = []; - - $scope.urls.push({ - title: "Local", - tagline: "URL for the machine you are running BrowserSync on", - url: urls.local, - icon: "imac" - }); - - if (urls.external) { - $scope.urls.push({ - title: "External", - tagline: "Other devices on the same wifi network", - url: urls.external, - icon: "wifi" - }); - } - - if (urls.tunnel) { - $scope.urls.push({ - title: "Tunnel", - tagline: "Secure HTTPS public url", - url: urls.tunnel, - icon: "globe" - }); - } - - /** - * - */ - $scope.sendAllTo = function (path) { - Clients.sendAllTo(path); - $rootScope.$emit("notify:flash", { - heading: "Instruction sent:", - message: "Sync all Browsers to: " + path - }); - }; - } - - /** - * Display the snippet when in snippet mode - */ - angular - .module("BrowserSync") - .directive("snippetInfo", function () { - return { - restrict: "E", - replace: true, - scope: { - "options": "=" - }, - templateUrl: "snippet-info.html", - controller: ["$scope", function snippetInfoController() {/*noop*/}] - }; - }); - -})(angular); \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/overview/overview.html b/web/node_modules/browser-sync-ui/lib/plugins/overview/overview.html deleted file mode 100644 index 047f91d..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/overview/overview.html +++ /dev/null @@ -1,25 +0,0 @@ -
-
-

- - {{ctrl.section.title}} -

-
- - - - -
-
-
- -
-

Current Connections

-

Connected browsers will be listed here.

- - - -
-
- -
\ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/overview/overview.plugin.js b/web/node_modules/browser-sync-ui/lib/plugins/overview/overview.plugin.js deleted file mode 100644 index b6ca04c..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/overview/overview.plugin.js +++ /dev/null @@ -1,51 +0,0 @@ -const PLUGIN_NAME = "Overview"; - -/** - * @type {{plugin: Function, plugin:name: string, markup: string}} - */ -module.exports = { - /** - * Plugin init - */ - "plugin": function () { /* noop */ }, - - /** - * Hooks - */ - "hooks": { - "markup": fileContent("/overview.html"), - "client:js": fileContent("/overview.client.js"), - "templates": [ - getPath("/snippet-info.html"), - getPath("/url-info.html") - ], - "page": { - path: "/", - title: PLUGIN_NAME, - template: "overview.html", - controller: PLUGIN_NAME.replace(" ", "") + "Controller", - order: 1, - icon: "cog" - } - }, - /** - * Plugin name - */ - "plugin:name": PLUGIN_NAME -}; - -/** - * @param filepath - * @returns {*} - */ -function getPath (filepath) { - return require("path").join(__dirname, filepath); -} - -/** - * @param filepath - * @returns {*} - */ -function fileContent (filepath) { - return require("fs").readFileSync(getPath(filepath), "utf-8"); -} \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/overview/snippet-info.html b/web/node_modules/browser-sync-ui/lib/plugins/overview/snippet-info.html deleted file mode 100644 index 8349e63..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/overview/snippet-info.html +++ /dev/null @@ -1,10 +0,0 @@ -
-
-
- -
-

Place this snippet somewhere before the closing </body> tag in your website

-
{{options.snippet}}
- -
-
\ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/overview/url-info.html b/web/node_modules/browser-sync-ui/lib/plugins/overview/url-info.html deleted file mode 100644 index b74305c..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/overview/url-info.html +++ /dev/null @@ -1,45 +0,0 @@ -
-
-
-
- -
-

{{url.title}}

-

{{url.url}}

- -
-
-
-
-
-
- -
-

Serving files from

-
    -
  • {{url}}
  • -
-
-
-
-
-
-
- -
-

Proxying:

-

- {{options.proxy.target}} -

-
-
-
\ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/plugins/plugins.client.js b/web/node_modules/browser-sync-ui/lib/plugins/plugins/plugins.client.js deleted file mode 100644 index ece644b..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/plugins/plugins.client.js +++ /dev/null @@ -1,85 +0,0 @@ -/** - * - */ -(function (angular) { - - var SECTION_NAME = "plugins"; - - angular - .module("BrowserSync") - .controller("PluginsController", [ - "options", - "Socket", - "pagesConfig", - PluginsPageController - ]); - - /** - * @param options - * @param Socket - * @param pagesConfig - * @constructor - */ - function PluginsPageController(options, Socket, pagesConfig) { - - - var ctrl = this; - ctrl.section = pagesConfig[SECTION_NAME]; - - ctrl.options = options.bs; - ctrl.uiOptions = options.ui; - - /** - * Don't show this UI as user plugin - */ - var filtered = ctrl.options.userPlugins.filter(function (item) { - return item.name !== "UI"; - }).map(function (item) { - item.title = item.name; - return item; - }); - - var named = filtered.reduce(function (all, item) { - all[item.name] = item; - return all; - }, {}); - - /** - * @type {{loading: boolean}} - */ - ctrl.ui = { - loading: false, - plugins: filtered, - named: named - }; - - /** - * Toggle a pluginrs - */ - ctrl.togglePlugin = function (plugin) { - Socket.uiEvent({ - namespace: SECTION_NAME, - event: "set", - data: plugin - }); - }; - - /** - * Set the state of many options - * @param value - */ - ctrl.setMany = function (value) { - Socket.uiEvent({ - namespace: SECTION_NAME, - event: "setMany", - data: value - }); - ctrl.ui.plugins = ctrl.ui.plugins.map(function (item) { - item.active = value; - return item; - }); - }; - } - -})(angular); - diff --git a/web/node_modules/browser-sync-ui/lib/plugins/plugins/plugins.html b/web/node_modules/browser-sync-ui/lib/plugins/plugins/plugins.html deleted file mode 100644 index f870a2f..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/plugins/plugins.html +++ /dev/null @@ -1,33 +0,0 @@ -
-

- - {{ctrl.section.title}} -

-
- - -
-
- -%pluginlist% - -
-
-
-

Sorry, no plugins were loaded

-

You can either write your own plugin (guide coming soon!) or Search NPM - for packages that contain the keywords browser sync plugin -

-
-
-
\ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/plugins/plugins.plugin.js b/web/node_modules/browser-sync-ui/lib/plugins/plugins/plugins.plugin.js deleted file mode 100644 index 7461673..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/plugins/plugins.plugin.js +++ /dev/null @@ -1,74 +0,0 @@ -const PLUGIN_NAME = "Plugins"; - -/** - * @type {{plugin: Function, plugin:name: string, markup: string}} - */ -module.exports = { - /** - * @param ui - * @param bs - */ - "plugin": function (ui, bs) { - - ui.listen("plugins", { - - "set": function (data) { - bs.events.emit("plugins:configure", data); - }, - - "setMany": function (data) { - - if (data.value !== true) { - data.value = false; - } - - bs.getUserPlugins() - .filter(function (item) { - return item.name !== "UI "; // todo dupe code server/client - }) - .forEach(function (item) { - item.active = data.value; - bs.events.emit("plugins:configure", item); - }); - } - }); - }, - /** - * Hooks - */ - "hooks": { - "markup": fileContent("plugins.html"), - "client:js": fileContent("/plugins.client.js"), - "templates": [ - //getPath("plugins.directive.html") - ], - "page": { - path: "/plugins", - title: PLUGIN_NAME, - template: "plugins.html", - controller: PLUGIN_NAME + "Controller", - order: 4, - icon: "plug" - } - }, - /** - * Plugin name - */ - "plugin:name": PLUGIN_NAME -}; - -/** - * @param filepath - * @returns {*} - */ -function getPath (filepath) { - return require("path").join(__dirname, filepath); -} - -/** - * @param filepath - * @returns {*} - */ -function fileContent (filepath) { - return require("fs").readFileSync(getPath(filepath), "utf-8"); -} \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/client-files.js b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/client-files.js deleted file mode 100644 index cc06162..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/client-files.js +++ /dev/null @@ -1,48 +0,0 @@ -var files = [ - { - name: "weinre", - context: "remote-debug", - active: false, - title: "Remote Debugger (weinre)", - tagline: "", - hidden: "Access remote debugger (opens in a new tab)

" - }, - { - type: "css", - context: "remote-debug", - id: "__browser-sync-pesticide__", - active: false, - file: __dirname + "/css/pesticide.min.css", - title: "CSS Outlining", - served: false, - name: "pesticide", - src: "/browser-sync/pesticide.css", - tagline: "Add simple CSS outlines to all elements. (powered by Pesticide.io)", - hidden: "" - }, - { - type: "css", - context: "remote-debug", - id: "__browser-sync-pesticidedepth__", - active: false, - file: __dirname + "/css/pesticide-depth.css", - title: "CSS Depth Outlining", - served: false, - name: "pesticide-depth", - src: "/browser-sync/pesticide-depth.css", - tagline: "Add CSS box-shadows to all elements. (powered by Pesticide.io)", - hidden: "" - }, - { - type: "js", - context: "n/a", - id: "__browser-sync-gridoverlay__", - active: false, - file: __dirname + "/overlay-grid/js/grid-overlay.js", - served: false, - name: "overlay-grid-js", - src: "/browser-sync/grid-overlay-js.js" - } -]; - -module.exports.files = files; \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/compression.html b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/compression.html deleted file mode 100644 index 7ae3827..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/compression.html +++ /dev/null @@ -1,19 +0,0 @@ -
-
-
-
- - -
-
-
-

{{ctrl.compression.title}}

-

-
-
-
\ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/compression.js b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/compression.js deleted file mode 100644 index aa8c5e1..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/compression.js +++ /dev/null @@ -1,33 +0,0 @@ -var Immutable = require("immutable"); - -module.exports.init = function (ui, bs) { - - var optPath = ["remote-debug", "compression"]; - - ui.setOptionIn(optPath, Immutable.Map({ - name: "compression", - title: "Compression", - active: false, - tagline: "Add Gzip Compression to all responses" - })); - - var methods = { - toggle: function (value) { - if (value !== true) { - value = false; - } - if (value) { - ui.setOptionIn(optPath.concat("active"), true); - bs.addMiddleware("", require("compression")(), {id: "ui-compression", override: true}); - } else { - ui.setOptionIn(optPath.concat("active"), false); - bs.removeMiddleware("ui-compression"); - } - }, - event: function (event) { - methods[event.event](event.data); - } - }; - - return methods; -}; \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/css/pesticide-depth.css b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/css/pesticide-depth.css deleted file mode 100755 index f6b4e8f..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/css/pesticide-depth.css +++ /dev/null @@ -1,498 +0,0 @@ -/* - pesticide v1.0.0 . @mrmrs . MIT -*/ -body { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -article { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -nav { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -aside { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -section { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -header { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -footer { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -h1 { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -h2 { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -h3 { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -h4 { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -h5 { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -h6 { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -main { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -address { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -div { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -p { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -hr { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -pre { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -blockquote { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -ol { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -ul { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -li { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -dl { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -dt { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -dd { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -figure { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -figcaption { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -table { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -caption { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -thead { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -tbody { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -tfoot { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -tr { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -th { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -td { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -col { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -colgroup { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -button { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -datalist { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -fieldset { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -form { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -input { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -keygen { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -label { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -legend { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -meter { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -optgroup { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -option { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -output { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -progress { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -select { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -textarea { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -details { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -summary { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -command { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -menu { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -del { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -ins { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -img { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -iframe { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -embed { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -object { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -param { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -video { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -audio { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -source { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -canvas { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -track { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -map { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -area { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -a { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -em { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -strong { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -i { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -b { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -u { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -s { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -small { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -abbr { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -q { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -cite { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -dfn { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -sub { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -sup { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -time { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -code { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -kbd { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -samp { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -var { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -mark { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -bdi { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -bdo { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -ruby { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -rt { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -rp { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -span { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -br { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} -wbr { - -webkit-box-shadow: 0 0 1rem rgba(0,0,0,0.6); - box-shadow: 0 0 1rem rgba(0,0,0,0.6); - background-color: rgba(255,255,255,0.25); -} diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/css/pesticide.css b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/css/pesticide.css deleted file mode 100755 index ff1e3e9..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/css/pesticide.css +++ /dev/null @@ -1,201 +0,0 @@ -/* - pesticide v1.0.0 . @mrmrs . MIT -*/ - { -body - outline: 1px solid #2980b9 !important; -article - outline: 1px solid #3498db !important; -nav - outline: 1px solid #0088c3 !important; -aside - outline: 1px solid #33a0ce !important; -section - outline: 1px solid #66b8da !important; -header - outline: 1px solid #99cfe7 !important; -footer - outline: 1px solid #cce7f3 !important; -h1 - outline: 1px solid #162544 !important; -h2 - outline: 1px solid #314e6e !important; -h3 - outline: 1px solid #3e5e85 !important; -h4 - outline: 1px solid #449baf !important; -h5 - outline: 1px solid #c7d1cb !important; -h6 - outline: 1px solid #4371d0 !important; -main - outline: 1px solid #2f4f90 !important; -address - outline: 1px solid #1a2c51 !important; -div - outline: 1px solid #036cdb !important; - outline: 1px solid #ac050b !important; -hr - outline: 1px solid #ff063f !important; -pre - outline: 1px solid #850440 !important; -blockquote - outline: 1px solid #f1b8e7 !important; -ol - outline: 1px solid #ff050c !important; -ul - outline: 1px solid #d90416 !important; -li - outline: 1px solid #d90416 !important; -dl - outline: 1px solid #fd3427 !important; -dt - outline: 1px solid #ff0043 !important; -dd - outline: 1px solid #e80174 !important; -figure - outline: 1px solid #f0b !important; -figcaption - outline: 1px solid #bf0032 !important; -table - outline: 1px solid #0c9 !important; -caption - outline: 1px solid #37ffc4 !important; -thead - outline: 1px solid #98daca !important; -tbody - outline: 1px solid #64a7a0 !important; -tfoot - outline: 1px solid #22746b !important; -tr - outline: 1px solid #86c0b2 !important; -th - outline: 1px solid #a1e7d6 !important; -td - outline: 1px solid #3f5a54 !important; -col - outline: 1px solid #6c9a8f !important; -colgroup - outline: 1px solid #6c9a9d !important; -button - outline: 1px solid #da8301 !important; -datalist - outline: 1px solid #c06000 !important; -fieldset - outline: 1px solid #d95100 !important; -form - outline: 1px solid #d23600 !important; -input - outline: 1px solid #fca600 !important; -keygen - outline: 1px solid #b31e00 !important; -label - outline: 1px solid #ee8900 !important; -legend - outline: 1px solid #de6d00 !important; -meter - outline: 1px solid #e8630c !important; -optgroup - outline: 1px solid #b33600 !important; -option - outline: 1px solid #ff8a00 !important; -output - outline: 1px solid #ff9619 !important; -progress - outline: 1px solid #e57c00 !important; -select - outline: 1px solid #e26e0f !important; -textarea - outline: 1px solid #cc5400 !important; -details - outline: 1px solid #33848f !important; -summary - outline: 1px solid #60a1a6 !important; -command - outline: 1px solid #438da1 !important; -menu - outline: 1px solid #449da6 !important; -del - outline: 1px solid #bf0000 !important; -ins - outline: 1px solid #400000 !important; -img - outline: 1px solid #22746b !important; -iframe - outline: 1px solid #64a7a0 !important; -embed - outline: 1px solid #98daca !important; -object - outline: 1px solid #0c9 !important; -param - outline: 1px solid #37ffc4 !important; -video - outline: 1px solid #6ee866 !important; -audio - outline: 1px solid #027353 !important; -source - outline: 1px solid #012426 !important; -canvas - outline: 1px solid #a2f570 !important; -track - outline: 1px solid #59a600 !important; -map - outline: 1px solid #7be500 !important; -area - outline: 1px solid #305900 !important; -a - outline: 1px solid #ff62ab !important; -em - outline: 1px solid #800b41 !important; -strong - outline: 1px solid #ff1583 !important; -i - outline: 1px solid #803156 !important; -b - outline: 1px solid #cc1169 !important; -u - outline: 1px solid #ff0430 !important; - outline: 1px solid #f805e3 !important; -small - outline: 1px solid #d107b2 !important; -abbr - outline: 1px solid #4a0263 !important; -q - outline: 1px solid #240018 !important; -cite - outline: 1px solid #64003c !important; -dfn - outline: 1px solid #b4005a !important; -sub - outline: 1px solid #dba0c8 !important; -sup - outline: 1px solid #cc0256 !important; -time - outline: 1px solid #d6606d !important; -code - outline: 1px solid #e04251 !important; -kbd - outline: 1px solid #5e001f !important; -samp - outline: 1px solid #9c0033 !important; -var - outline: 1px solid #d90047 !important; -mark - outline: 1px solid #ff0053 !important; -bdi - outline: 1px solid #bf3668 !important; -bdo - outline: 1px solid #6f1400 !important; -ruby - outline: 1px solid #ff7b93 !important; -rt - outline: 1px solid #ff2f54 !important; -rp - outline: 1px solid #803e49 !important; -span - outline: 1px solid #cc2643 !important; -br - outline: 1px solid #db687d !important; -wbr - outline: 1px solid #db175b !important; -} diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/css/pesticide.min.css b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/css/pesticide.min.css deleted file mode 100755 index 3a23045..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/css/pesticide.min.css +++ /dev/null @@ -1,395 +0,0 @@ -body { - outline: 1px solid #2980b9 !important -} - -article { - outline: 1px solid #3498db !important -} - -nav { - outline: 1px solid #0088c3 !important -} - -aside { - outline: 1px solid #33a0ce !important -} - -section { - outline: 1px solid #66b8da !important -} - -header { - outline: 1px solid #99cfe7 !important -} - -footer { - outline: 1px solid #cce7f3 !important -} - -h1 { - outline: 1px solid #162544 !important -} - -h2 { - outline: 1px solid #314e6e !important -} - -h3 { - outline: 1px solid #3e5e85 !important -} - -h4 { - outline: 1px solid #449baf !important -} - -h5 { - outline: 1px solid #c7d1cb !important -} - -h6 { - outline: 1px solid #4371d0 !important -} - -main { - outline: 1px solid #2f4f90 !important -} - -address { - outline: 1px solid #1a2c51 !important -} - -div { - outline: 1px solid #036cdb !important -} - -p { - outline: 1px solid #ac050b !important -} - -hr { - outline: 1px solid #ff063f !important -} - -pre { - outline: 1px solid #850440 !important -} - -blockquote { - outline: 1px solid #f1b8e7 !important -} - -ol { - outline: 1px solid #ff050c !important -} - -ul { - outline: 1px solid #d90416 !important -} - -li { - outline: 1px solid #d90416 !important -} - -dl { - outline: 1px solid #fd3427 !important -} - -dt { - outline: 1px solid #ff0043 !important -} - -dd { - outline: 1px solid #e80174 !important -} - -figure { - outline: 1px solid #f0b !important -} - -figcaption { - outline: 1px solid #bf0032 !important -} - -table { - outline: 1px solid #0c9 !important -} - -caption { - outline: 1px solid #37ffc4 !important -} - -thead { - outline: 1px solid #98daca !important -} - -tbody { - outline: 1px solid #64a7a0 !important -} - -tfoot { - outline: 1px solid #22746b !important -} - -tr { - outline: 1px solid #86c0b2 !important -} - -th { - outline: 1px solid #a1e7d6 !important -} - -td { - outline: 1px solid #3f5a54 !important -} - -col { - outline: 1px solid #6c9a8f !important -} - -colgroup { - outline: 1px solid #6c9a9d !important -} - -button { - outline: 1px solid #da8301 !important -} - -datalist { - outline: 1px solid #c06000 !important -} - -fieldset { - outline: 1px solid #d95100 !important -} - -form { - outline: 1px solid #d23600 !important -} - -input { - outline: 1px solid #fca600 !important -} - -keygen { - outline: 1px solid #b31e00 !important -} - -label { - outline: 1px solid #ee8900 !important -} - -legend { - outline: 1px solid #de6d00 !important -} - -meter { - outline: 1px solid #e8630c !important -} - -optgroup { - outline: 1px solid #b33600 !important -} - -option { - outline: 1px solid #ff8a00 !important -} - -output { - outline: 1px solid #ff9619 !important -} - -progress { - outline: 1px solid #e57c00 !important -} - -select { - outline: 1px solid #e26e0f !important -} - -textarea { - outline: 1px solid #cc5400 !important -} - -details { - outline: 1px solid #33848f !important -} - -summary { - outline: 1px solid #60a1a6 !important -} - -command { - outline: 1px solid #438da1 !important -} - -menu { - outline: 1px solid #449da6 !important -} - -del { - outline: 1px solid #bf0000 !important -} - -ins { - outline: 1px solid #400000 !important -} - -img { - outline: 1px solid #22746b !important -} - -iframe { - outline: 1px solid #64a7a0 !important -} - -embed { - outline: 1px solid #98daca !important -} - -object { - outline: 1px solid #0c9 !important -} - -param { - outline: 1px solid #37ffc4 !important -} - -video { - outline: 1px solid #6ee866 !important -} - -audio { - outline: 1px solid #027353 !important -} - -source { - outline: 1px solid #012426 !important -} - -canvas { - outline: 1px solid #a2f570 !important -} - -track { - outline: 1px solid #59a600 !important -} - -map { - outline: 1px solid #7be500 !important -} - -area { - outline: 1px solid #305900 !important -} - -a { - outline: 1px solid #ff62ab !important -} - -em { - outline: 1px solid #800b41 !important -} - -strong { - outline: 1px solid #ff1583 !important -} - -i { - outline: 1px solid #803156 !important -} - -b { - outline: 1px solid #cc1169 !important -} - -u { - outline: 1px solid #ff0430 !important -} - -s { - outline: 1px solid #f805e3 !important -} - -small { - outline: 1px solid #d107b2 !important -} - -abbr { - outline: 1px solid #4a0263 !important -} - -q { - outline: 1px solid #240018 !important -} - -cite { - outline: 1px solid #64003c !important -} - -dfn { - outline: 1px solid #b4005a !important -} - -sub { - outline: 1px solid #dba0c8 !important -} - -sup { - outline: 1px solid #cc0256 !important -} - -time { - outline: 1px solid #d6606d !important -} - -code { - outline: 1px solid #e04251 !important -} - -kbd { - outline: 1px solid #5e001f !important -} - -samp { - outline: 1px solid #9c0033 !important -} - -var { - outline: 1px solid #d90047 !important -} - -mark { - outline: 1px solid #ff0053 !important -} - -bdi { - outline: 1px solid #bf3668 !important -} - -bdo { - outline: 1px solid #6f1400 !important -} - -ruby { - outline: 1px solid #ff7b93 !important -} - -rt { - outline: 1px solid #ff2f54 !important -} - -rp { - outline: 1px solid #803e49 !important -} - -span { - outline: 1px solid #cc2643 !important -} - -br { - outline: 1px solid #db687d !important -} - -wbr { - outline: 1px solid #db175b !important -} diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/latency/latency.client.js b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/latency/latency.client.js deleted file mode 100644 index 511ac18..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/latency/latency.client.js +++ /dev/null @@ -1,43 +0,0 @@ -(function (angular) { - - const SECTION_NAME = "remote-debug"; - /** - * Display the snippet when in snippet mode - */ - angular - .module("BrowserSync") - .directive("latency", function () { - return { - restrict: "E", - replace: true, - scope: { - "options": "=" - }, - templateUrl: "latency.html", - controller: ["$scope", "Socket", latencyDirectiveControlller], - controllerAs: "ctrl" - }; - }); - - /** - * @param $scope - * @param Socket - */ - function latencyDirectiveControlller($scope, Socket) { - - var ctrl = this; - var ns = SECTION_NAME + ":latency"; - - ctrl.latency = $scope.options[SECTION_NAME]["latency"]; - - ctrl.alterLatency = function () { - Socket.emit("ui", { - namespace: ns, - event: "adjust", - data: { - rate: ctrl.latency.rate - } - }); - }; - } -})(angular); diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/latency/latency.html b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/latency/latency.html deleted file mode 100644 index feae946..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/latency/latency.html +++ /dev/null @@ -1,12 +0,0 @@ -
- - - -
- diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/latency/latency.js b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/latency/latency.js deleted file mode 100644 index d67dd67..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/latency/latency.js +++ /dev/null @@ -1,44 +0,0 @@ -var Immutable = require("immutable"); - -module.exports.init = function (ui, bs) { - - var timeout = 0; - var optPath = ["remote-debug", "latency"]; - - ui.setOptionIn(optPath, Immutable.Map({ - name: "latency", - title: "Latency", - active: false, - tagline: "Simulate slower connections by throttling the response time of each request.", - rate: 0 - })); - - var methods = { - toggle: function (value) { - if (value !== true) { - value = false; - } - if (value) { - ui.setOptionIn(optPath.concat("active"), true); - bs.addMiddleware("*", function (req, res, next) { - setTimeout(next, timeout); - }, {id: "cp-latency", override: true}); - } else { - ui.setOptionIn(optPath.concat("active"), false); - bs.removeMiddleware("cp-latency"); - } - }, - adjust: function (data) { - timeout = parseFloat(data.rate) * 1000; - var saved = ui.options.getIn(optPath.concat("rate")); - if (saved !== data.rate) { - ui.setOptionIn(optPath.concat("rate"), timeout/1000); - } - }, - event: function (event) { - methods[event.event](event.data); - } - }; - - return methods; -}; \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/no-cache.html b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/no-cache.html deleted file mode 100644 index 1bea016..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/no-cache.html +++ /dev/null @@ -1,19 +0,0 @@ -
-
-
-
- - -
-
-
-

{{ctrl.noCache.title}}

-

-
-
-
\ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/no-cache.js b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/no-cache.js deleted file mode 100644 index f84d8b9..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/no-cache.js +++ /dev/null @@ -1,38 +0,0 @@ -var Immutable = require("immutable"); - -module.exports.init = function (ui, bs) { - - var optPath = ["remote-debug", "no-cache"]; - - ui.setOptionIn(optPath, Immutable.Map({ - name: "no-cache", - title: "No Cache", - active: false, - tagline: "Disable all Browser Caching" - })); - - var methods = { - toggle: function (value) { - if (value !== true) { - value = false; - } - if (value) { - ui.setOptionIn(optPath.concat("active"), true); - bs.addMiddleware("*", function (req, res, next) { - res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); - res.setHeader("Pragma", "no-cache"); - res.setHeader("Expires", "0"); - next(); - }, {id: "ui-no-cache", override: true}); - } else { - ui.setOptionIn(optPath.concat("active"), false); - bs.removeMiddleware("ui-no-cache"); - } - }, - event: function (event) { - methods[event.event](event.data); - } - }; - - return methods; -}; \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/css/grid-overlay-horizontal.css b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/css/grid-overlay-horizontal.css deleted file mode 100755 index f6b4a44..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/css/grid-overlay-horizontal.css +++ /dev/null @@ -1,16 +0,0 @@ -{{selector}}:after { - position: absolute; - width: auto; - height: auto; - z-index: 9999; - content: ''; - display: block; - pointer-events: none; - top: {{offsetY}}; - right: 0; - bottom: 0; - left: {{offsetX}}; - background-color: transparent; - background-image: linear-gradient({{color}} 1px, transparent 1px); - background-size: 100% {{size}}; -} diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/css/grid-overlay-vertical.css b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/css/grid-overlay-vertical.css deleted file mode 100755 index 1e6e67c..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/css/grid-overlay-vertical.css +++ /dev/null @@ -1,16 +0,0 @@ -{{selector}}:before { - position: absolute; - width: auto; - height: auto; - z-index: 9999; - content: ''; - display: block; - pointer-events: none; - top: {{offsetY}}; - right: 0; - bottom: 0; - left: {{offsetX}}; - background-color: transparent; - background-image: linear-gradient(90deg, {{color}} 1px, transparent 1px); - background-size: {{size}} 100%; -} \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/js/grid-overlay.js b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/js/grid-overlay.js deleted file mode 100644 index dc09e08..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/js/grid-overlay.js +++ /dev/null @@ -1,18 +0,0 @@ -(function (window, bs, undefined) { - - var styleElem = bs.addDomNode({ - placement: "head", - attrs: { - "type": "text/css", - id: "__bs_overlay-grid-styles__" - }, - tagName: "style" - }); - - bs.socket.on("ui:remote-debug:css-overlay-grid", function (data) { - styleElem.innerHTML = data.innerHTML; - }); - - bs.socket.emit("ui:remote-debug:css-overlay-grid:ready"); - -}(window, window.___browserSync___)); \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/overlay-grid.client.js b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/overlay-grid.client.js deleted file mode 100644 index 833139d..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/overlay-grid.client.js +++ /dev/null @@ -1,56 +0,0 @@ -(function (angular) { - - const SECTION_NAME = "remote-debug"; - - /** - * Display the snippet when in snippet mode - */ - angular - .module("BrowserSync") - .directive("cssGrid", function () { - return { - restrict: "E", - replace: true, - scope: { - "options": "=" - }, - templateUrl: "overlay-grid.html", - controller: ["$scope", "Socket", overlayGridDirectiveControlller], - controllerAs: "ctrl" - }; - }); - - /** - * @param $scope - * @param Socket - */ - function overlayGridDirectiveControlller($scope, Socket) { - - var ctrl = this; - - ctrl.overlayGrid = $scope.options[SECTION_NAME]["overlay-grid"]; - ctrl.size = ctrl.overlayGrid.size; - - var ns = SECTION_NAME + ":overlay-grid"; - - ctrl.alter = function (value) { - Socket.emit("ui", { - namespace: ns, - event: "adjust", - data: value - }); - }; - - ctrl.toggleAxis = function (axis, value) { - Socket.emit("ui", { - namespace: ns, - event: "toggle:axis", - data: { - axis: axis, - value: value - } - }); - }; - } - -})(angular); diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/overlay-grid.html b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/overlay-grid.html deleted file mode 100644 index 1de1c83..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/overlay-grid.html +++ /dev/null @@ -1,106 +0,0 @@ -
- -
-
-
- - -
- -
-
-
-
-
- - -
- -
-
-
-
-
- - - -
- -
-
-
-
-
-
-
- - - -
- -
-
-
-
-
- - - -
- -
-
-
-
-
-
-
- - -
-
-
-
- - -
-
-
-
\ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/overlay-grid.js b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/overlay-grid.js deleted file mode 100644 index 1c5692a..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/overlay-grid/overlay-grid.js +++ /dev/null @@ -1,101 +0,0 @@ -var Immutable = require("immutable"); -var fs = require("fs"); -var path = require("path"); -var baseHorizontal = fs.readFileSync(path.resolve(__dirname, "css/grid-overlay-horizontal.css"), "utf8"); -var baseVertical = fs.readFileSync(path.resolve(__dirname, "css/grid-overlay-vertical.css"), "utf8"); - -function template (string, obj) { - obj = obj || {}; - return string.replace(/\{\{(.+?)\}\}/g, function () { - if (obj[arguments[1]]) { - return obj[arguments[1]]; - } - return ""; - }); -} - -function getCss(opts) { - - var base = opts.selector + " {position:relative;}"; - - if (opts.horizontal) { - base += baseHorizontal; - } - - if (opts.vertical) { - base += baseVertical; - } - - return template(base, opts); -} - -module.exports.init = function (ui) { - - const TRANSMIT_EVENT = "ui:remote-debug:css-overlay-grid"; - const READY_EVENT = "ui:remote-debug:css-overlay-grid:ready"; - const OPT_PATH = ["remote-debug", "overlay-grid"]; - - var defaults = { - offsetY: "0", - offsetX: "0", - size: "16px", - selector: "body", - color: "rgba(0, 0, 0, .2)", - horizontal: true, - vertical: true - }; - - ui.clients.on("connection", function (client) { - client.on(READY_EVENT, function () { - client.emit(TRANSMIT_EVENT, { - innerHTML: getCss(ui.options.getIn(OPT_PATH).toJS()) - }); - }); - }); - - ui.setOptionIn(OPT_PATH, Immutable.Map({ - name: "overlay-grid", - title: "Overlay CSS Grid", - active: false, - tagline: "Add an adjustable CSS overlay grid to your webpage", - innerHTML: "" - }).merge(defaults)); - - - var methods = { - toggle: function (value) { - if (value !== true) { - value = false; - } - if (value) { - ui.setOptionIn(OPT_PATH.concat("active"), true); - ui.enableElement({name: "overlay-grid-js"}); - } else { - ui.setOptionIn(OPT_PATH.concat("active"), false); - ui.disableElement({name: "overlay-grid-js"}); - ui.clients.emit("ui:element:remove", {id: "__bs_overlay-grid-styles__"}); - } - }, - adjust: function (data) { - - ui.setOptionIn(OPT_PATH, ui.getOptionIn(OPT_PATH).merge(data)); - - ui.clients.emit(TRANSMIT_EVENT, { - innerHTML: getCss(ui.options.getIn(OPT_PATH).toJS()) - }); - }, - "toggle:axis": function (item) { - - ui.setOptionIn(OPT_PATH.concat([item.axis]), item.value); - - ui.clients.emit(TRANSMIT_EVENT, { - innerHTML: getCss(ui.options.getIn(OPT_PATH).toJS()) - }); - }, - event: function (event) { - methods[event.event](event.data); - } - }; - - return methods; -}; \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/remote-debug.client.js b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/remote-debug.client.js deleted file mode 100644 index 335f2e9..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/remote-debug.client.js +++ /dev/null @@ -1,155 +0,0 @@ -(function (angular) { - - const SECTION_NAME = "remote-debug"; - - angular - .module("BrowserSync") - .controller("RemoteDebugController", [ - "options", - "Socket", - "pagesConfig", - RemoteDebugController - ]); - - /** - * @param options - * @param Socket - * @param pagesConfig - */ - function RemoteDebugController(options, Socket, pagesConfig) { - - var ctrl = this; - ctrl.options = options.bs; - ctrl.uiOptions = options.ui; - ctrl.clientFiles = options.ui.clientFiles || {}; - ctrl.section = pagesConfig[SECTION_NAME]; - ctrl.overlayGrid = options.ui[SECTION_NAME]["overlay-grid"]; - ctrl.items = []; - - if (Object.keys(ctrl.clientFiles).length) { - Object.keys(ctrl.clientFiles).forEach(function (key) { - if (ctrl.clientFiles[key].context === SECTION_NAME) { - ctrl.items.push(ctrl.clientFiles[key]); - } - }); - } - - ctrl.toggleClientFile = function (item) { - if (item.name === "weinre") { - return ctrl.toggleWeinre(item); - } - if (item.active) { - return ctrl.enable(item); - } - return ctrl.disable(item); - }; - - ctrl.toggleWeinre = function (item) { - Socket.uiEvent({ - namespace: SECTION_NAME + ":weinre", - event: "toggle", - data: item.active - }); - }; - - ctrl.toggleOverlayGrid = function (item) { - var ns = SECTION_NAME + ":overlay-grid"; - Socket.uiEvent({ - namespace: ns, - event: "toggle", - data: item.active - }); - }; - - ctrl.enable = function (item) { - Socket.uiEvent({ - namespace: SECTION_NAME + ":files", - event: "enableFile", - data: item - }); - }; - - ctrl.disable = function (item) { - Socket.uiEvent({ - namespace: SECTION_NAME + ":files", - event: "disableFile", - data: item - }); - }; - } - - /** - * Display the snippet when in snippet mode - */ - angular - .module("BrowserSync") - .directive("noCache", function () { - return { - restrict: "E", - replace: true, - scope: { - "options": "=" - }, - templateUrl: "no-cache.html", - controller: ["$scope", "Socket", noCacheDirectiveControlller], - controllerAs: "ctrl" - }; - }); - - /** - * @param $scope - * @param Socket - */ - function noCacheDirectiveControlller ($scope, Socket) { - - var ctrl = this; - - ctrl.noCache = $scope.options[SECTION_NAME]["no-cache"]; - - ctrl.toggleLatency = function (item) { - Socket.emit("ui:no-cache", { - event: "toggle", - data: item.active - }); - }; - } - - - /** - * Display the snippet when in snippet mode - */ - angular - .module("BrowserSync") - .directive("compression", function () { - return { - restrict: "E", - replace: true, - scope: { - "options": "=" - }, - templateUrl: "compression.html", - controller: ["$scope", "Socket", compressionDirectiveControlller], - controllerAs: "ctrl" - }; - }); - - /** - * @param $scope - * @param Socket - */ - function compressionDirectiveControlller ($scope, Socket) { - - var ctrl = this; - - ctrl.compression = $scope.options[SECTION_NAME]["compression"]; - - ctrl.toggleLatency = function (item) { - Socket.emit("ui:compression", { - event: "toggle", - data: item.active - }); - }; - } - -})(angular); - diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/remote-debug.html b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/remote-debug.html deleted file mode 100644 index a79025c..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/remote-debug.html +++ /dev/null @@ -1,23 +0,0 @@ -
-

- - {{ctrl.section.title}} -

-
- - -
-
- - - - diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/remote-debug.plugin.js b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/remote-debug.plugin.js deleted file mode 100644 index 098ee59..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/remote-debug.plugin.js +++ /dev/null @@ -1,96 +0,0 @@ -var weinre = require("./weinre"); -//var compression = require("./compression"); -//var noCachePlugin = require("./no-cache"); -var overlayPlugin = require("./overlay-grid/overlay-grid"); -var clientFiles = require("./client-files"); - -const PLUGIN_NAME = "Remote Debug"; - -/** - * @type {{plugin: Function, plugin:name: string, markup: string}} - */ -module.exports = { - /** - * @param ui - * @param bs - */ - "plugin": function (ui, bs) { - - if (bs.options.get("scheme") === "https") { - ui.setMany(function (item) { - item.deleteIn(["clientFiles", "weinre"]); - }); - } else { - ui.weinre = weinre.init(ui); - } - - ui.overlayGrid = overlayPlugin.init(ui, bs); - - //ui.noCache = noCachePlugin.init(ui, bs); - //ui.compression = compression.init(ui, bs); - - /** - * Listen for file events - */ - ui.listen("remote-debug:files", { - "enableFile": function (file) { - ui.enableElement(file); - }, - "disableFile": function (file) { - ui.disableElement(file); - } - }); - - /** - * Listen for weinre toggles - */ - ui.listen("remote-debug:weinre", ui.weinre); - - /** - * Listen for overlay-grid events - */ - ui.listen("remote-debug:overlay-grid", ui.overlayGrid); - }, - /** - * Hooks - */ - "hooks": { - "markup": fileContent("remote-debug.html"), - "client:js": [ - fileContent("/remote-debug.client.js"), - fileContent("/overlay-grid/overlay-grid.client.js") - ], - "templates": [ - getPath("/overlay-grid/overlay-grid.html") - ], - "page": { - path: "/remote-debug", - title: PLUGIN_NAME, - template: "remote-debug.html", - controller: PLUGIN_NAME.replace(" ", "") + "Controller", - order: 4, - icon: "bug" - }, - elements: clientFiles.files - }, - /** - * Plugin name - */ - "plugin:name": PLUGIN_NAME -}; - -/** - * @param filepath - * @returns {*} - */ -function getPath (filepath) { - return require("path").join(__dirname, filepath); -} - -/** - * @param filepath - * @returns {*} - */ -function fileContent (filepath) { - return require("fs").readFileSync(getPath(filepath), "utf-8"); -} \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/weinre.js b/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/weinre.js deleted file mode 100644 index c661366..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/remote-debug/weinre.js +++ /dev/null @@ -1,201 +0,0 @@ -var url = require("url"); -var Immutable = require("immutable"); -var path = require("path"); - -var weinreApp; - -const WEINRE_NAME = "weinre-debug"; -const WEINRE_ID = "#browsersync"; -const WEINRE_ELEM_ID = "__browser-sync-weinre__"; - -var weinreTargetUrl = { - protocol: "http:", - pathname: "/target/target-script-min.js", - hash: WEINRE_ID -}; - -var weinreClientUrl = { - protocol: "http:", - pathname: "/client/", - hash: WEINRE_ID -}; - -/** - * Prepare weinre for later possible use. - * @param ui - */ -function init (ui) { - - var hostUrl = getHostUrl(ui, ui.bs); - var weinrePort = ui.getOptionIn(["weinre", "port"]); - - weinreTargetUrl.hostname = hostUrl.hostname; - weinreClientUrl.hostname = hostUrl.hostname; - weinreClientUrl.port = weinrePort; - weinreTargetUrl.port = weinrePort; - - ui.setOption(WEINRE_NAME, Immutable.fromJS({ - name: WEINRE_NAME, - active: false, - url: false, - targetUrl: url.format(weinreTargetUrl), - clientUrl: url.format(weinreClientUrl), - port: weinrePort - })); - - setWeinreClientUrl(ui, url.format(weinreClientUrl)); - - var methods = { - toggle: function (data) { - toggleWeinre(ui.socket, ui.clients, ui, ui.bs, data); - }, - event: function (event) { - methods[event.event](event.data); - } - }; - - return methods; -} - -/** - * Get a suitable host URL for weinre - * @param ui - * @param bs - * @returns {*} - */ -function getHostUrl(ui, bs) { - - var url = bs.getOptionIn(["urls", "external"]); - - if (!url) { - url = bs.getOptionIn(["urls", "local"]); - } - - return require("url").parse(url); -} - - -/** - * @param ui - * @param weinreClientUrl - */ -function setWeinreClientUrl(ui, weinreClientUrl) { - var weinre = ui.options.getIn(["clientFiles", "weinre"]).toJS(); - ui.setMany(function (item) { - item.setIn(["clientFiles", "weinre", "hidden"], weinre.hidden.replace("%s", weinreClientUrl)); - return item; - }); -} - -/** - * @param socket - * @param clients - * @param ui - * @param bs - * @param value - */ -function toggleWeinre (socket, clients, ui, bs, value) { - - if (value !== true) { - value = false; - } - - if (value) { - - var _debugger = enableWeinre(ui, bs); - - // set the state of weinre - ui.setMany(function (item) { - item.setIn([WEINRE_NAME, "active"], true); - item.setIn([WEINRE_NAME, "url"], _debugger.url); - item.setIn([WEINRE_NAME, "active"], true); - item.setIn(["clientFiles", "weinre", "active"], true); - }, {silent: true}); - - - // Let the UI know about it - socket.emit("ui:weinre:enabled", _debugger); - - var fileitem = { - type: "js", - src: ui.getOptionIn([WEINRE_NAME, "targetUrl"]), - id: WEINRE_ELEM_ID - }; - - // Add the element to all clients - ui.addElement(clients, fileitem); - - // Save for page refreshes - //clientScripts = clientScripts.set("weinre", fileitem); - - } else { - - // Stop it - disableWeinre(ui, bs); - - //clientScripts = clientScripts.remove("weinre"); - - // Reset the state - ui.setOptionIn([WEINRE_NAME, "active"], false, {silent: false}); // Force a reload here - ui.setOptionIn(["clientFiles", "weinre", "active"], false); // Force a reload here - - // Let the UI know - socket.emit("ui:weinre:disabled"); - - // Reload all browsers to remove weinre elements/JS - clients.emit("browser:reload"); - - } -} - -/** - * Enable the debugger - * @param ui - * @param bs - * @returns {{url: string, port: number}} - */ -function enableWeinre (ui, bs) { - - if (weinreApp && typeof weinreApp.destroy === "function") { - weinreApp.destroy(); - weinreApp = undefined; - } - - var port = ui.getOptionIn([WEINRE_NAME, "port"]); - - var logger = require(path.join(path.dirname(require.resolve("weinre")), "utils.js")); - - logger.log = function (message) { - ui.logger.debug("[weinre]: %s", message); - }; - - var weinre = require("weinre"); - var external = getHostUrl(ui, bs); - - weinreApp = weinre.run({ - httpPort: port, - boundHost: external.hostname, - verbose: false, - debug: false, - readTimeout: 5, - deathTimeout: 15 }); - - require("server-destroy")(weinreApp); - - return ui.options.get(WEINRE_NAME).toJS(); -} - -/** - * @param ui - * @returns {any|*} - */ -function disableWeinre (ui) { - if (weinreApp) { - weinreApp.close(); - weinreApp = false; - } - return ui.options.get(WEINRE_NAME).toJS(); -} - -module.exports.init = init; -module.exports.toggleWeinre = toggleWeinre; diff --git a/web/node_modules/browser-sync-ui/lib/plugins/sync-options/sync-options.client.js b/web/node_modules/browser-sync-ui/lib/plugins/sync-options/sync-options.client.js deleted file mode 100644 index 96a807c..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/sync-options/sync-options.client.js +++ /dev/null @@ -1,94 +0,0 @@ -(function (angular) { - - const SECTION_NAME = "sync-options"; - - angular - .module("BrowserSync") - .controller("SyncOptionsController", [ - "Socket", - "options", - "pagesConfig", - SyncOptionsController - ]); - - /** - * @param Socket - * @param options - * @param pagesConfig - * @constructor - */ - function SyncOptionsController(Socket, options, pagesConfig) { - - var ctrl = this; - ctrl.options = options.bs; - ctrl.section = pagesConfig[SECTION_NAME]; - - ctrl.setMany = function (value) { - Socket.uiEvent({ - namespace: SECTION_NAME, - event: "setMany", - data: { - value: value - } - }); - ctrl.syncItems = ctrl.syncItems.map(function (item) { - item.value = value; - return item; - }); - }; - - /** - * Toggle Options - * @param item - */ - ctrl.toggleSyncItem = function (item) { - Socket.uiEvent({ - namespace: SECTION_NAME, - event: "set", - data: { - path: item.path, - value: item.value - } - }); - }; - - ctrl.syncItems = []; - - var taglines = { - clicks: "Mirror clicks across devices", - scroll: "Mirror scroll position across devices", - "ghostMode.submit": "Form Submissions will be synced", - "ghostMode.inputs": "Text inputs (including text-areas) will be synced", - "ghostMode.toggles": "Radio + Checkboxes changes will be synced", - codeSync: "Reload or Inject files they change" - }; - - // If watching files, add the code-sync toggle - ctrl.syncItems.push(addItem("codeSync", ["codeSync"], ctrl.options.codeSync, taglines["codeSync"])); - - Object.keys(ctrl.options.ghostMode).forEach(function (item) { - if (item !== "forms" && item !== "location") { - ctrl.syncItems.push(addItem(item, ["ghostMode", item], ctrl.options.ghostMode[item], taglines[item])); - } - }); - - Object.keys(ctrl.options.ghostMode.forms).forEach(function (item) { - ctrl.syncItems.push(addItem("Forms: " + item, ["ghostMode", "forms", item], ctrl.options.ghostMode["forms"][item], taglines["ghostMode." + item])); - }); - - function addItem (item, path, value, tagline) { - return { - value: value, - name: item, - path: path, - title: ucfirst(item), - tagline: tagline - }; - } - } - - function ucfirst (string) { - return string.charAt(0).toUpperCase() + string.slice(1); - } - -})(angular); diff --git a/web/node_modules/browser-sync-ui/lib/plugins/sync-options/sync-options.html b/web/node_modules/browser-sync-ui/lib/plugins/sync-options/sync-options.html deleted file mode 100644 index 527b591..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/sync-options/sync-options.html +++ /dev/null @@ -1,25 +0,0 @@ -
-
-

- - {{ctrl.section.title}} -

-
-
- - -
- - -
\ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/plugins/sync-options/sync-options.plugin.js b/web/node_modules/browser-sync-ui/lib/plugins/sync-options/sync-options.plugin.js deleted file mode 100644 index e8090e2..0000000 --- a/web/node_modules/browser-sync-ui/lib/plugins/sync-options/sync-options.plugin.js +++ /dev/null @@ -1,66 +0,0 @@ -const PLUGIN_NAME = "Sync Options"; - -/** - * @type {{plugin: Function, plugin:name: string, hooks: object}} - */ -module.exports = { - - "plugin": function (ui, bs) { - - ui.listen("sync-options", { - - "set": function (data) { - - ui.logger.debug("Setting option: {magenta:%s}:{cyan:%s}", data.path.join("."), data.value); - bs.setOptionIn(data.path, data.value); - - }, - - "setMany": function (data) { - - ui.logger.debug("Setting Many options..."); - - if (data.value !== true) { - data.value = false; - } - - bs.setMany(function (item) { - [ - ["codeSync"], - ["ghostMode", "clicks"], - ["ghostMode", "scroll"], - ["ghostMode", "forms", "inputs"], - ["ghostMode", "forms", "toggles"], - ["ghostMode", "forms", "submit"] - ].forEach(function (option) { - item.setIn(option, data.value); - }); - }); - - return bs; - } - }); - }, - "hooks": { - "markup": fileContent("sync-options.html"), - "client:js": fileContent("sync-options.client.js"), - "templates": [], - "page": { - path: "/sync-options", - title: PLUGIN_NAME, - template: "sync-options.html", - controller: PLUGIN_NAME.replace(" ", "") + "Controller", - order: 2, - icon: "sync" - } - }, - "plugin:name": PLUGIN_NAME -}; - -function getPath (filepath) { - return require("path").join(__dirname, filepath); -} - -function fileContent (filepath) { - return require("fs").readFileSync(getPath(filepath), "utf-8"); -} diff --git a/web/node_modules/browser-sync-ui/lib/resolve-plugins.js b/web/node_modules/browser-sync-ui/lib/resolve-plugins.js deleted file mode 100644 index 6abb26a..0000000 --- a/web/node_modules/browser-sync-ui/lib/resolve-plugins.js +++ /dev/null @@ -1,117 +0,0 @@ -var fs = require("fs"); -var path = require("path"); -var Immutable = require("immutable"); - -/** - * Take Browsersync plugins and determine if - * any UI is provided by looking at data in the the - * modules package.json file - * @param plugins - * @returns {*} - */ -module.exports = function (plugins) { - return require("immutable") - .fromJS(plugins) - /** - * Exclude the UI - */ - .filter(function (plugin) { - return plugin.get("name") !== "UI"; - }) - /** - * Attempt to retrieve a plugins package.json file - */ - .map(function (plugin) { - - var moduleName = plugin.getIn(["opts", "moduleName"]); - var pkg = {}; - - if (!moduleName) { - return plugin; - } - - try { - pkg = require("immutable").fromJS(require(path.join(moduleName, "package.json"))); - } catch (e) { - console.error(e); - return plugin; - } - - plugin = plugin.set("pkg", pkg); - - return plugin.set("relpath", path.dirname(require.resolve(moduleName))); - }) - /** - * Try to load markup for each plugin - */ - .map(function (plugin) { - - if (!plugin.hasIn(["pkg", "browser-sync:ui"])) { - return plugin; - } - - var markup = plugin.getIn(["pkg", "browser-sync:ui", "hooks", "markup"]); - - if (markup) { - plugin = plugin.set("markup", fs.readFileSync(path.resolve(plugin.get("relpath"), markup), "utf8")); - } - - return plugin; - }) - /** - * Load any template files for the plugin - */ - .map(function (plugin) { - - if (!plugin.hasIn(["pkg", "browser-sync:ui"])) { - return plugin; - } - - return resolveIfPluginHas(["pkg", "browser-sync:ui", "hooks", "templates"], "templates", plugin); - }) - /** - * Try to load Client JS for each plugin - */ - .map(function (plugin) { - - if (!plugin.hasIn(["pkg", "browser-sync:ui"])) { - return plugin; - } - - return resolveIfPluginHas(["pkg", "browser-sync:ui", "hooks", "client:js"], "client:js", plugin); - }); -}; - -/** - * If a plugin contains this option path, resolve/read the files - * @param {Array} optPath - How to access the collection - * @param {String} propName - Key for property access - * @param {Immutable.Map} plugin - * @returns {*} - */ -function resolveIfPluginHas(optPath, propName, plugin) { - var opt = plugin.getIn(optPath); - if (opt.size) { - return plugin.set( - propName, - resolvePluginFiles(opt, plugin.get("relpath")) - ); - } - return plugin; -} - -/** - * Read & store a file from a plugin - * @param {Array|Immutable.List} collection - * @param {String} relPath - * @returns {any} - */ -function resolvePluginFiles (collection, relPath) { - return Immutable.fromJS(collection.reduce(function (all, item) { - var full = path.join(relPath, item); - if (fs.existsSync(full)) { - all[full] = fs.readFileSync(full, "utf8"); - } - return all; - }, {})); -} diff --git a/web/node_modules/browser-sync-ui/lib/server.js b/web/node_modules/browser-sync-ui/lib/server.js deleted file mode 100644 index ff67ca9..0000000 --- a/web/node_modules/browser-sync-ui/lib/server.js +++ /dev/null @@ -1,221 +0,0 @@ -var http = require("http"); -var fs = require("fs"); -var path = require("path"); -var config = require("./config"); -var svg = publicFile(config.defaults.public.svg); -var indexPage = publicFile(config.defaults.indexPage); -//var css = publicFile(config.defaults.public.css); -var header = staticFile(config.defaults.components.header); -var footer = staticFile(config.defaults.components.footer); -var zlib = require("zlib"); - -/** - * @param {UI} ui - * @returns {*} - */ -function startServer(ui) { - - var connect = ui.bs.utils.connect; - var serveStatic = ui.bs.utils.serveStatic; - - /** - * Create a connect server - */ - var app = connect(); - var socketJs = getSocketJs(ui); - var jsFilename = "/" + md5(socketJs, 10) + ".js"; - //var cssFilename = "/" + md5(css, 10) + ".css"; - - /** - * Create a single big file with all deps - */ - //app.use(serveFile(jsFilename, "js", socketJs)); - app.use(serveFile(config.defaults.socketJs, "js", socketJs)); - - // also serve for convenience/testing - app.use(serveFile(config.defaults.pagesConfig, "js", ui.pagesConfig)); - - // - app.use(serveFile(config.defaults.clientJs, "js", ui.clientJs)); - - /** - * Add any markup from plugins/hooks/templates - */ - insertPageMarkupFromHooks( - app, - ui.pages, - indexPage - .replace("%pageMarkup%", ui.pageMarkup) - .replace("%templates%", ui.templates) - .replace("%svg%", svg) - .replace("%header%", header) - .replace(/%footer%/g, footer) - ); - - /** - * gzip css - */ - //app.use(serveFile(cssFilename, "css", css)); - - app.use(serveStatic(path.join(__dirname, "../public"))); - - /** - * all public dir as static - */ - app.use(serveStatic(publicDir(""))); - - /** - * History API fallback - */ - app.use(require("connect-history-api-fallback")); - - /** - * Development use - */ - app.use("/node_modules", serveStatic(packageDir("node_modules"))); - - /** - * Return the server. - */ - return { - server: http.createServer(app), - app: app - }; -} - -/** - * @param app - * @param pages - * @param markup - */ -function insertPageMarkupFromHooks(app, pages, markup) { - - var cached; - - app.use(function (req, res, next) { - - if (req.url === "/" || pages[req.url.slice(1)]) { - res.writeHead(200, {"Content-Type": "text/html", "Content-Encoding": "gzip"}); - if (!cached) { - var buf = new Buffer(markup, "utf-8"); - zlib.gzip(buf, function (_, result) { - cached = result; - res.end(result); - }); - } else { - res.end(cached); - } - } else { - next(); - } - }); -} - -/** - * Serve Gzipped files & cache them - * @param app - * @param all - */ -var gzipCache = {}; -function serveFile(path, type, string) { - var typemap = { - js: "application/javascript", - css: "text/css" - }; - return function (req, res, next) { - if (req.url !== path) { - return next(); - } - - res.writeHead(200, { - "Content-Type": typemap[type], - "Content-Encoding": "gzip", - "Cache-Control": "no-cache, no-store, must-revalidate", - "Expires": 0, - "Pragma": "no-cache" - }); - - if (gzipCache[path]) { - return res.end(gzipCache[path]); - } - var buf = new Buffer(string, "utf-8"); - zlib.gzip(buf, function (_, result) { - gzipCache[path] = result; - res.end(result); - }); - }; -} - - -/** - * @param cp - * @returns {string} - */ -function getSocketJs (cp) { - - return [ - cp.bs.getSocketIoScript(), - cp.bs.getExternalSocketConnector({namespace: "/browser-sync-cp"}) - ].join(";"); -} - -///** -// * @returns {*} -// * @param filepath -// */ -//function fileContent (filepath) { -// return fs.readFileSync(require.resolve(filepath), "utf8"); -//} - -/** - * @param src - * @param length - */ -function md5(src, length) { - var crypto = require("crypto"); - var hash = crypto.createHash("md5").update(src, "utf8").digest("hex"); - return hash.slice(0, length); -} - -/** - * CWD directory helper for static dir - * @param {string} filepath - * @returns {string} - */ -function publicDir (filepath) { - return path.join(__dirname, "/../public" + filepath) || ""; -} - -/** - * @param {string} filepath - * @returns {string|string} - */ -function staticDir (filepath) { - return path.join(__dirname, "/../static" + filepath) || ""; -} - -/** - * @param {string} filepath - * @returns {*} - */ -function publicFile(filepath) { - return fs.readFileSync(publicDir(filepath), "utf-8"); -} - -/** - * @param filepath - * @returns {*} - */ -function staticFile(filepath) { - return fs.readFileSync(staticDir(filepath), "utf-8"); -} - -/** - * @param {string} filepath - * @returns {string} - */ -function packageDir (filepath) { - return path.join(__dirname, "/../" + filepath); -} - -module.exports = startServer; \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/transform.options.js b/web/node_modules/browser-sync-ui/lib/transform.options.js deleted file mode 100644 index 0ac3862..0000000 --- a/web/node_modules/browser-sync-ui/lib/transform.options.js +++ /dev/null @@ -1,25 +0,0 @@ -var path = require("path"); - -module.exports = function (bs) { - /** - * Transform server options to offer additional functionality - * @param bs - */ - - var options = bs.options; - var server = options.server; - var cwd = bs.cwd; - - /** - * Transform server option - */ - if (server) { - if (Array.isArray(server.baseDir)) { - server.baseDirs = options.server.baseDir.map(function (item) { - return path.join(cwd, item); - }); - } else { - server.baseDirs = [path.join(cwd, server.baseDir)]; - } - } -}; \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/transforms.js b/web/node_modules/browser-sync-ui/lib/transforms.js deleted file mode 100644 index 6423b54..0000000 --- a/web/node_modules/browser-sync-ui/lib/transforms.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - "mode": function (obj) { - if (obj.get("server")) { - return "Server"; - } - if (obj.get("proxy")) { - return "Proxy"; - } - return "Snippet"; - } -}; \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/lib/urls.js b/web/node_modules/browser-sync-ui/lib/urls.js deleted file mode 100644 index e69de29..0000000 diff --git a/web/node_modules/browser-sync-ui/lib/utils.js b/web/node_modules/browser-sync-ui/lib/utils.js deleted file mode 100644 index 5bf87e7..0000000 --- a/web/node_modules/browser-sync-ui/lib/utils.js +++ /dev/null @@ -1,35 +0,0 @@ -var url = require("url"); -var http = require("http"); - -/** - * @param localUrl - * @param urlPath - * @returns {*} - */ -function createUrl(localUrl, urlPath) { - return url.parse(url.resolve(localUrl, urlPath)); -} - -/** - * @param url - * @param cb - */ -function verifyUrl(url, cb) { - - url.headers = { - "accept": "text/html" - }; - - http.get(url, function (res) { - if (res.statusCode === 200) { - cb(null, res); - } else { - cb("not 200"); - } - }).on("error", function(e) { - console.log("Got error: " + e.message); - }); -} - -module.exports.createUrl = createUrl; -module.exports.verifyUrl = verifyUrl; diff --git a/web/node_modules/browser-sync-ui/package.json b/web/node_modules/browser-sync-ui/package.json deleted file mode 100644 index 75f2df6..0000000 --- a/web/node_modules/browser-sync-ui/package.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "_args": [ - [ - "browser-sync-ui@0.6.3", - "/home/treharne/Documents/web/cdt-py" - ] - ], - "_development": true, - "_from": "browser-sync-ui@0.6.3", - "_id": "browser-sync-ui@0.6.3", - "_inBundle": false, - "_integrity": "sha1-ZApTfBgGiTA9W+krxHa568RBwLw=", - "_location": "/browser-sync-ui", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "browser-sync-ui@0.6.3", - "name": "browser-sync-ui", - "escapedName": "browser-sync-ui", - "rawSpec": "0.6.3", - "saveSpec": null, - "fetchSpec": "0.6.3" - }, - "_requiredBy": [ - "/browser-sync" - ], - "_resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-0.6.3.tgz", - "_spec": "0.6.3", - "_where": "/home/treharne/Documents/web/cdt-py", - "author": { - "name": "Shane Osbourne" - }, - "bugs": { - "url": "https://github.com/BrowserSync/UI/issues" - }, - "dependencies": { - "async-each-series": "0.1.1", - "connect-history-api-fallback": "^1.1.0", - "immutable": "^3.7.6", - "server-destroy": "1.0.1", - "stream-throttle": "^0.1.3", - "weinre": "^2.0.0-pre-I0Z7U9OV" - }, - "description": "User Interface for BrowserSync", - "devDependencies": { - "angular": "~1.4.8", - "angular-route": "~1.4.8", - "angular-sanitize": "~1.4.8", - "angular-touch": "~1.4.8", - "browser-sync": "^2.11.0", - "bs-console-info": "1.0.2", - "bs-fullscreen-message": "1.0.2", - "bs-html-injector": "3.0.2", - "bs-latency": "1.0.0", - "bs-rewrite-rules": "1.0.0", - "chai": "^3.4.1", - "compression": "^1.6.0", - "crossbow": "4.0.8", - "crossbow-sass": "4.0.3", - "easy-svg": "1.0.5", - "eazy-logger": "^2.1.2", - "gulp": "^3.9.0", - "gulp-autoprefixer": "^3.1.0", - "gulp-contribs": "0.0.3", - "gulp-filter": "^3.0.1", - "gulp-jshint": "^2.0.0", - "gulp-rename": "^1.2.2", - "jshint": "^2.8.0", - "lodash": "^3.10.1", - "mocha": "^2.3.4", - "no-abs": "0.0.0", - "nodemon": "^1.8.1", - "object-path": "^0.9.2", - "parallelshell": "^2.0.0", - "pretty-js": "^0.1.8", - "protractor": "3.3.0", - "request": "^2.67.0", - "sinon": "^1.17.2", - "store": "^1.3.20", - "supertest": "^1.1.0", - "uglify-js": "^2.6.1", - "vinyl-fs": "2.4.3", - "webpack": "^1.12.10" - }, - "files": [ - "index.js", - "lib", - "public", - "static", - "templates" - ], - "homepage": "http://www.browsersync.io/", - "keywords": [ - "browser sync", - "live reload", - "css injection", - "action sync" - ], - "license": "Apache-2.0", - "name": "browser-sync-ui", - "repository": { - "type": "git", - "url": "git+https://github.com/BrowserSync/UI.git" - }, - "scripts": { - "e2e": "./test/pro.sh", - "selenium": "webdriver-manager start", - "test": "cb test" - }, - "version": "0.6.3" -} diff --git a/web/node_modules/browser-sync-ui/public/css/components.css b/web/node_modules/browser-sync-ui/public/css/components.css deleted file mode 100644 index b835947..0000000 --- a/web/node_modules/browser-sync-ui/public/css/components.css +++ /dev/null @@ -1,15 +0,0 @@ -svg { - width: 100%; - height: 100%; - opacity: 1; - fill: currentColor !important; - -webkit-transition: .3s; - transition: .3s; } - svg.icon-hidden { - opacity: 0; } - -body, html { - height: auto; } - -.tube { - padding: 0 14px; } diff --git a/web/node_modules/browser-sync-ui/public/css/core.css b/web/node_modules/browser-sync-ui/public/css/core.css deleted file mode 100644 index 2a0128a..0000000 --- a/web/node_modules/browser-sync-ui/public/css/core.css +++ /dev/null @@ -1,2 +0,0 @@ - -/*# sourceMappingURL=core.css.map */ diff --git a/web/node_modules/browser-sync-ui/public/css/core.css.map b/web/node_modules/browser-sync-ui/public/css/core.css.map deleted file mode 100755 index ea26f86..0000000 --- a/web/node_modules/browser-sync-ui/public/css/core.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":[],"names":[],"mappings":"","file":"core.css","sourceRoot":"/source/","sourcesContent":[]} \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/public/css/core.min.css b/web/node_modules/browser-sync-ui/public/css/core.min.css deleted file mode 100644 index 3ca590b..0000000 --- a/web/node_modules/browser-sync-ui/public/css/core.min.css +++ /dev/null @@ -1,4 +0,0 @@ -*,:after,:before{box-sizing:border-box}blockquote,caption,dd,dl,fieldset,form,h1,h2,h3,h4,h5,h6,hr,legend,ol,p,pre,table,td,th,ul{margin:0;padding:0}abbr[title],dfn[title]{cursor:help}a,ins,u{text-decoration:none}ins{border-bottom:1px solid}img{font-style:italic}button,input,label,option,select,textarea{cursor:pointer}.text-input:active,.text-input:focus,textarea:active,textarea:focus{cursor:text;outline:none} - -/*! normalize.css v3.0.1 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@font-face{font-family:source_sans;src:url(../fonts/source-sans/sourcesanspro-it-webfont.eot);src:url(../fonts/source-sans/sourcesanspro-it-webfont.eot?#iefix) format("embedded-opentype"),url(../fonts/source-sans/sourcesanspro-it-webfont.woff2) format("woff2"),url(../fonts/source-sans/sourcesanspro-it-webfont.woff) format("woff"),url(../fonts/source-sans/sourcesanspro-it-webfont.ttf) format("truetype"),url(../fonts/source-sans/sourcesanspro-it-webfont.svg#source_sans_proitalic) format("svg");font-weight:400;font-style:italic}@font-face{font-family:source_sans;src:url(../fonts/source-sans/sourcesanspro-bold-webfont.eot);src:url(../fonts/source-sans/sourcesanspro-bold-webfont.eot?#iefix) format("embedded-opentype"),url(../fonts/source-sans/sourcesanspro-bold-webfont.woff2) format("woff2"),url(../fonts/source-sans/sourcesanspro-bold-webfont.woff) format("woff"),url(../fonts/source-sans/sourcesanspro-bold-webfont.ttf) format("truetype"),url(../fonts/source-sans/sourcesanspro-bold-webfont.svg#source_sans_probold) format("svg");font-weight:700;font-style:normal}@font-face{font-family:source_sans;src:url(../fonts/source-sans/sourcesanspro-regular-webfont.eot);src:url(../fonts/source-sans/sourcesanspro-regular-webfont.eot?#iefix) format("embedded-opentype"),url(../fonts/source-sans/sourcesanspro-regular-webfont.woff2) format("woff2"),url(../fonts/source-sans/sourcesanspro-regular-webfont.woff) format("woff"),url(../fonts/source-sans/sourcesanspro-regular-webfont.ttf) format("truetype"),url(../fonts/source-sans/sourcesanspro-regular-webfont.svg#source_sans_proregular) format("svg");font-weight:400;font-style:normal}@-webkit-keyframes a{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes a{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}html{overflow-x:hidden;overflow-y:auto;height:100%;font:112.5%/1.5 source_sans,Lucida Grande,Lucida Sans,sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-webkit-font-smoothing:antialiased}@media only screen and (min-width:600px){html{height:100vh}}body{min-height:100%;max-width:100%;overflow-x:hidden;overflow-y:auto;background:#fff;color:#777;text-rendering:optimizeLegibility}@media only screen and (min-width:600px){body{height:100vh;overflow-y:hidden}}main{position:relative}@media only screen and (min-width:600px){main{overflow:hidden}}dl ol,dl ul,ol ol,ol ul,ul ol,ul ul{margin-bottom:0}ol,ul{margin-left:27px}ul{list-style:disc}ul ul{list-style:circle}ol{list-style:decimal}ol ol{list-style:lower-alpha}dt{font-weight:700}dd+dt{padding-top:14px}table{margin-top:14px;width:100%}td,th{padding:7px 14px;border-bottom:1px solid #f0f0f0;text-align:left;vertical-align:top}th{font-weight:700}thead tr:last-child th{border-bottom:2px solid #f0f0f0}[colspan]{text-align:center}[colspan="1"]{text-align:left}[rowspan]{vertical-align:middle}[rowspan="1"]{vertical-align:top}hr{clear:both;margin-bottom:27px;border:none;border-bottom:1px solid #f0f0f0;padding-bottom:14px;height:1px}[bs-grid]{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;-ms-flex-flow:wrap;flex-flow:wrap}[bs-grid]>*{width:100%;padding-top:14px;padding-bottom:7px}@media only screen and (min-width:750px){[bs-grid~=desk-2] [bs-grid-item]{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%}}@media only screen and (min-width:1000px){[bs-grid~=wide-4] [bs-grid-item]{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%}}@media only screen and (min-width:600px){[bs-grid-item~=padded-right]{padding-right:54px}}.ng-cloak,.x-ng-cloak,[data-ng-cloak],[ng-cloak],[ng\:cloak],[x-ng-cloak]{display:none!important}[bs-header]{position:relative;background:#222}@media only screen and (min-width:600px){[bs-header]{display:-webkit-box;display:-ms-flexbox;display:flex}}[bs-header] [bs-header-row~=brand]{height:60px}[bs-header] [bs-header-row]{position:relative;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex}[bs-header] [bs-header-row] *{margin-top:auto;margin-bottom:auto}[bs-header] [bs-list~=header]{width:100%;padding-left:75px;font-size:14px;font-size:.77778rem}[bs-header] [bs-list~=header],[bs-header] [bs-list~=header] a{color:#fff}[bs-header] [bs-list~=header]:hover,[bs-header] [bs-list~=header] a:hover{text-decoration:none}[bs-header] [bs-list~=header] a{display:block;position:relative}[bs-header] [bs-list~=header] a:hover{color:#81be00;text-shadow:1px 1px 3px #000}[bs-toggle]{font-size:24px;font-size:1.33333rem;position:absolute;right:0;cursor:pointer;width:55px;text-align:center;height:60px;line-height:60px;color:#fff;-webkit-transition:background .2s;transition:background .2s;text-shadow:1px 1px 2px #00262c;border-left:1px solid #222;border-bottom:1px solid #222}@media only screen and (min-width:600px){[bs-toggle]{display:none}}[bs-toggle] svg{position:absolute;top:14px;left:12px;height:30px;width:30px;pointer-events:none}[bs-toggle] svg[bs-state=alt]{opacity:0}[bs-toggle]:hover{background:#444}[bs-toggle].active svg{opacity:0}[bs-toggle].active svg[bs-state=alt]{opacity:1!important}[bs-link~=version]{color:#777;margin-left:7px;font-size:20px;font-size:1.11111rem;position:relative;top:4px}[bs-link~=version]:focus,[bs-link~=version]:hover{color:#f54747}[bs-sidebar]{position:relative;background:#444}@media only screen and (min-width:600px){[bs-sidebar]{width:240px}[bs-sidebar]:after{content:" ";width:10px;height:100%;position:absolute;right:0;top:0;z-index:4;background:-webkit-linear-gradient(left,transparent,rgba(0,0,0,.2));background:linear-gradient(90deg,transparent 0,rgba(0,0,0,.2))}}[bs-section-nav]{background:#444;position:absolute;width:100%;-webkit-transform:translateX(-200%) translateY(20px) scale(1.2);transform:translateX(-200%) translateY(20px) scale(1.2);-webkit-transition-timing-function:cubic-bezier(.3,0,0,1.3);transition-timing-function:cubic-bezier(.3,0,0,1.3);-webkit-transition:all .3s;transition:all .3s;opacity:0;z-index:3}[bs-section-nav] ul{margin-bottom:0}[bs-section-nav] [bs-button]{text-transform:none;color:#ababab;width:100%;border-radius:0;text-align:left;border:0;position:relative;background:transparent;display:block;height:auto;padding:11px 0 11px 55px;border-bottom:1px solid #363636;font-size:16px;font-size:.88889rem;margin-bottom:0;box-shadow:0 0 0 0}[bs-section-nav] [bs-button] [bs-svg-icon]{top:14px;width:20px;height:20px}[bs-section-nav] [bs-button].active{background:#363636;z-index:3;color:#fff}[bs-section-nav] [bs-button].active [bs-svg-icon]{color:#f54747}[bs-section-nav] [bs-button]:hover{color:#fff;background:#363636}[bs-section-nav] [bs-button]:active{color:#fff;box-shadow:inset 0 1px 2px 0 rgba(0,0,0,.1);background:#292929}@media only screen and (min-width:600px){[bs-section-nav]{position:relative;-webkit-transform:translateX(0) translateY(0) scale(1);transform:translateX(0) translateY(0) scale(1)}[bs-section-nav].ready{opacity:1}}[bs-section-nav].active{-webkit-transform:translateX(0) translateY(0) scale(1);transform:translateX(0) translateY(0) scale(1);opacity:1}@media only screen and (min-width:600px){[bs-container]{display:-webkit-box;display:-ms-flexbox;display:flex}}[bs-content]{overflow-x:hidden;height:auto;position:relative;background:#fff;width:100%}@media only screen and (min-width:600px){[bs-content]{height:100vh;overflow-y:auto;-webkit-overflow-scrolling:touch;padding-bottom:59px;margin-top:1px;width:auto;-webkit-box-flex:1;-ms-flex:1;flex:1}}svg{width:100%;height:100%;opacity:1;fill:currentColor!important;-webkit-transition:.3s;transition:.3s}svg.icon-hidden{opacity:0}.icon{display:inline-block}.icon-trash{width:100%;max-width:26px;height:26px}.icon-word{width:100%;max-width:150px;height:100%;margin-left:15px;color:#fff}.icon-word svg{position:relative;top:-1px}.icon-logo{color:#fff;-webkit-transition:all .1s;transition:all .1s;width:55px;height:37px;text-align:center}.icon-logo:hover{color:#fff;-webkit-transform:scale(1.1);transform:scale(1.1)}[bs-svg-icon]{display:inline-block;line-height:inherit;position:relative;top:7px}[bs-svg-icon],[bs-svg-icon] use{width:27px;height:27px}address,blockquote,details,dl,fieldset,figcaption,figure,h1,h2,h3,h4,h5,h6,hgroup,ol,p,pre,table,ul{margin-bottom:14px}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{color:#444;font-weight:400;line-height:1;font-family:source_sans,Lucida Grande,Lucida Sans,sans-serif;margin-bottom:27px;-webkit-font-smoothing:antialiased}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-size:inherit;font-weight:400}.h1,h1{font-size:36px;font-size:2rem}.h2,h2{padding-top:14px;font-size:30px;font-size:1.66667rem}.h3,h3{font-size:18px;font-size:1rem;font-weight:700}.h4,.h5,.h6,h4,h5,h6{font-size:16px;font-size:.88889rem}[bs-heading]{background:#444;font-size:24px;font-size:1.33333rem;padding-left:55px;position:relative;line-height:52px;margin-top:0;margin-bottom:0;color:#fbfbfb;background:#3f3f3f;border-top:1px solid #3f3f3f}@media only screen and (min-width:600px){[bs-heading]{font-size:38px;font-size:2.11111rem;color:#444;background:#fbfbfb;padding-left:80px;border-top:0}[bs-heading]:before{display:none}}[bs-heading] [bs-svg-icon]{position:absolute;left:14px;top:11px}@media only screen and (min-width:600px){[bs-heading] [bs-svg-icon]{height:38px;width:38px;top:6px}}.lede{font-size:24px;font-size:1.33333rem}.small{font-size:14px;font-size:.77778rem}a{color:#f54747;-webkit-transition:background .3s ease,color .3s ease;transition:background .3s ease,color .3s ease}a:active,a:focus,a:hover{color:#000}a [class*=" icon-"],a [class^=icon-]{text-decoration:none}[bs-icon]{-webkit-transition:background .3s ease,color .3s ease;transition:background .3s ease,color .3s ease}.flush--bottom{margin-bottom:0!important}.text--cap{text-transform:capitalize}.color--lime{color:#81be00}.hidden{display:none}.hidden.active{display:block}[bs-stack]{margin-bottom:14px}span.sep{margin-left:5px;margin-right:5px}@media only screen and (min-width:600px){.width-100{width:100%!important}.width-90{width:90%!important}.width-80{width:80%!important}.width-70{width:70%!important}.width-60{width:60%!important}.width-50{width:50%!important}.width-40{width:40%!important}.width-30{width:30%!important}.width-20{width:20%!important}}@media only screen and (min-width:600px){[bs-width~="100"]{width:100%!important}[bs-width~="90"]{width:90%!important}[bs-width~="80"]{width:80%!important}[bs-width~="70"]{width:70%!important}[bs-width~="60"]{width:60%!important}[bs-width~="50"]{width:50%!important}[bs-width~="40"]{width:40%!important}[bs-width~="30"]{width:30%!important}[bs-width~="25"]{width:25%!important}[bs-width~="20"]{width:20%!important}[bs-width~="10"]{-webkit-box-flex:0!important;-ms-flex:0 0 10%!important;flex:0 0 10%!important}[bs-width~="5"]{-webkit-box-flex:0!important;-ms-flex:0 0 5%!important;flex:0 0 5%!important}}[bs-text~=lede]{font-size:18px;font-size:1rem}[bs-text~=mono]{font-weight:400;font-size:16px;font-size:.88889rem;font-family:monospace;color:#000}[bs-text~=micro]{font-size:12px;font-size:.66667rem;text-transform:uppercase;color:#d7d7d7;width:60px;display:inline-block;text-align:right;margin-right:5px}[bs-color~=white]{color:#fff}[bs-color~=success]{color:#81be00}@media only screen and (min-width:750px){[bs-visible~=not-desk]{display:none}}[bs-visible~=not-palm]{display:none!important}@media only screen and (min-width:600px){[bs-visible~=not-palm]{display:inherit!important}}@media only screen and (min-width:600px){[bs-visible~=palm]{display:none}}[bs-sep]{color:#d7d7d7;margin-left:3px;margin-right:3px}[bs-button]{font-size:16px;font-size:.88889rem;display:inline-block;border:1px solid #e30c0c;padding:7px 21px;width:auto;vertical-align:middle;background:#f54747;color:#fff;border-radius:3px;text-align:center;cursor:pointer;outline:none;-webkit-transition:color .2s,background .2s;transition:color .2s,background .2s;text-transform:uppercase;letter-spacing:1px;margin-bottom:14px;height:40px;-webkit-tap-highlight-color:transparent}[bs-button]:hover{background:#f21717}[bs-button]:focus,[bs-button]:hover{text-decoration:none;color:#fff}[bs-button]:active{color:#fff;box-shadow:inset 0 1px 0 0 rgba(0,0,0,.1);text-shadow:1px 1px 0 rgba(0,0,0,.4)}[bs-button].success{color:#81be00!important}[bs-button].success [bs-state~=success]{opacity:1}[bs-button].success [bs-state~=default]{opacity:0}[bs-button][disabled]{border-color:#d86464;background:#d86464;color:#f2aaaa}[bs-button] [bs-svg-icon]{position:absolute;top:11px;left:14px;width:16px;height:16px}[bs-button~=subtle]{background:#fff;color:#f54747;border-color:#e3e3e3}[bs-button~=subtle]:focus,[bs-button~=subtle]:hover{color:#f54747;background:#f0f0f0}[bs-button~=subtle]:focus{background:#fff}[bs-button~=subtle]:active{color:#f54747;text-shadow:1px 1px 1px rgba(0,0,0,.2);background:#f7f7f7}[bs-button~=subtle][disabled]{border-color:#e3e3e3;background:#f0f0f0;color:#f2aaaa}[bs-button~=subtle-alt]{background:#fff;color:#8a8a8a;border-color:#e3e3e3}[bs-button~=subtle-alt]:focus,[bs-button~=subtle-alt]:hover{color:#8a8a8a;background:#f0f0f0}[bs-button~=subtle-alt]:focus{background:#fff}[bs-button~=subtle-alt]:active{color:#8a8a8a;text-shadow:1px 1px 1px rgba(0,0,0,.2);background:#f7f7f7}[bs-button~=subtle-alt][disabled]{border-color:#e3e3e3;background:#f0f0f0;color:#bdbdbd}[bs-button~=size-small]{font-size:14px;font-size:.77778rem;padding:5px 14px;padding-top:7px;height:34px}[bs-button~=size-small] [bs-svg-icon]{top:9px;width:14px;height:14px}[bs-button~=icon]{padding-left:14px;padding-right:14px}[bs-button~=icon] [bs-svg-icon]{position:relative;top:2px;left:auto}[bs-button~=icon-left]{position:relative;padding-left:41px}[bs-button~=icon-left] [bs-svg-icon]{left:14px}[bs-button~=icon-right]{position:relative;padding-right:41px}[bs-button~=icon-right] [bs-svg-icon]{left:auto;right:14px}[bs-button-group]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;margin-bottom:14px}[bs-button-group] [bs-button]{border-radius:0;margin-bottom:0}[bs-button-group] [bs-button]:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}[bs-button-group] [bs-button]:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}[bs-button~=inline]{position:relative;background:transparent;color:#000;border-radius:0;border:0;text-transform:uppercase;box-shadow:0 0 0 0;font-size:14px;font-size:.77778rem;margin-bottom:0;padding-top:10px}[bs-button~=inline] [bs-checkbox]{margin-right:8px}[bs-button~=inline]:focus{background:transparent;color:#000}[bs-button~=inline]:hover{background:#f0f0f0;color:#000}[bs-button~=inline]:active{background:#d7d7d7;box-shadow:0 0 0 0}[bs-button~=success] [bs-svg-icon]{color:#81be00}[bs-button-row]{background:#fbfbfb;border-bottom:1px solid #d7d7d7}@media only screen and (min-width:600px){[bs-button-row]{padding-left:27px}}@media only screen and (min-width:600px){[bs-action~=menu-close],[bs-action~=menu-toggle]{display:none}}button,input,select{outline:none;vertical-align:middle;border-radius:3px;outline:0;height:40px;padding-left:7px;padding-right:14px;max-width:100%;font-family:source_sans,Lucida Grande,Lucida Sans,sans-serif;color:#000}[bs-code-input]{width:100%;border:0;border:1px dashed #f0f0f0;font-family:monospace;padding:14px}[bs-code-input]:focus{color:#4a90e2}[bs-heading-bar]{display:-webkit-box;display:-ms-flexbox;display:flex;margin-bottom:7px}[bs-heading-bar] [bs-input-label]{line-height:36px}[bs-heading-bar] [bs-button-group]{-webkit-box-flex:1;-ms-flex:1;flex:1;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;margin-bottom:auto;margin-top:auto}[bs-heading-bar] [bs-button-group] [bs-button]{padding:3px 5px;height:24px;font-size:10px}@media only screen and (min-width:600px){[bs-heading-bar] [bs-button-group] [bs-button]{padding:7px 14px;height:34px;font-size:14px}}[bs-textarea-input]{position:relative;margin-bottom:14px}[bs-textarea-input] [bs-tag]{left:-64px;color:#d08989}[bs-error~=offset]{position:absolute;top:0;left:0}[bs-input-label]{font-size:14px;font-size:.77778rem;position:relative;display:block;text-transform:uppercase;font-weight:700;color:#ababab;letter-spacing:.5px}@media only screen and (min-width:600px){[bs-input-label]{font-size:14px;font-size:.77778rem}}[bs-label-heading]{color:#000;font-weight:700}[bs-input]{padding:0;border-radius:3px;height:100%}[bs-input]>*{margin-top:auto;margin-bottom:auto}[bs-input] input{border:0;border-radius:0;padding:0;outline:0;font-size:16px;font-size:.88889rem;border-bottom:1px dashed #f0f0f0}[bs-input] input:focus{color:#4a90e2}[bs-input] input[type=text]{width:100%}[bs-input] input[type=radio]:checked+label{color:#4a90e2!important}[bs-input~=text]{height:auto}[bs-input~=text] input{font-family:monospace}[bs-input~=inline]{display:-webkit-box;display:-ms-flexbox;display:flex;height:auto}[bs-input~=inline] input:focus+label{text-decoration:underline}[bs-input~=inline]>*{margin-top:auto;margin-bottom:auto}[bs-input~=inline]>:first-child{margin-right:14px}.loader,.loader:after,.loader:before{background:#333;-webkit-animation:b .5s infinite ease-in-out;animation:b .5s infinite ease-in-out;width:1em;height:2em}.loader:after,.loader:before{position:absolute;top:0;content:''}.loader:before{left:-1.5em}.loader{opacity:1;-webkit-transition:all 1s;transition:all 1s;text-indent:-9999em;margin:8em auto;position:absolute;font-size:11px;-webkit-animation-delay:-.16s;animation-delay:-.16s;z-index:1;left:50%}.loader.behind{z-index:0}.loader.ready{opacity:0;-webkit-transform:translateY(-200%);transform:translateY(-200%)}.loader:after{left:1.5em;-webkit-animation-delay:-.32s;animation-delay:-.32s}@-webkit-keyframes b{0%,80%,to{box-shadow:0 0 #333;height:4em}40%{box-shadow:0 -2em #333;height:5em}}@keyframes b{0%,80%,to{box-shadow:0 0 #333;height:4em}40%{box-shadow:0 -2em #333;height:5em}}[bs-panel]{position:relative;background:#fff;padding:27px 0 14px;border-bottom:1px solid #f0f0f0}[bs-panel] [bs-text~=lede]{font-size:20px;font-size:1.11111rem;position:relative;margin-bottom:0;color:#000}@media only screen and (min-width:600px){[bs-panel] [bs-text~=lede]{font-size:24px;font-size:1.33333rem}}[bs-panel] [bs-text~=prefixed]{text-transform:none}[bs-panel] [bs-text~=prefixed] span{text-transform:uppercase;color:#f0f0f0;font-weight:200}[bs-panel~=switch].disabled{background:#fbfbfb}[bs-panel~=switch].disabled,[bs-panel~=switch].disabled [bs-text~=lede]{color:#ababab}[bs-panel~=switch] [bs-panel-content]{padding-left:81px;margin-bottom:14px}@media only screen and (min-width:600px){[bs-panel~=switch] [bs-panel-content]{padding-left:108px}[bs-panel~=switch] [bs-panel-content] [bs-panel-icon]{top:33px}}[bs-panel~=switch] [bs-panel-content~=basic]{padding-left:14px;padding-right:14px;max-width:none}[bs-panel~=switch] [bs-panel-content~=tight]{padding-left:0;padding-right:0;max-width:none}[bs-panel~=last]{border-bottom:2px solid #f0f0f0;position:relative}[bs-panel~=last]:after{content:" ";width:100%;height:1px;display:block;background:#f0f0f0;position:absolute;bottom:-4px;z-index:2}[bs-panel~=controls]{padding:0;background:#fbfbfb;border-bottom:1px solid #f0f0f0}@media only screen and (min-width:600px){[bs-panel~=controls]{padding:27px;padding-bottom:14px}}@media only screen and (min-width:600px){[bs-panel~=controls] [bs-heading]{margin-bottom:14px}}[bs-panel~=no-border]{border-bottom:0}[bs-panel~=outline]{border-bottom:1px solid #f0f0f0}[bs-panel-icon]{position:absolute;left:14px;top:30px}[bs-panel-icon] [bs-svg-icon]{color:#444;height:24px;width:24px;top:0}[bs-panel-content]{padding-left:54px;padding-right:14px}@media only screen and (min-width:600px){[bs-panel-content]{padding-left:108px}[bs-panel-content] [bs-panel-icon]{left:44px;top:27px}[bs-panel-content] [bs-panel-icon] [bs-svg-icon],[bs-panel-content] [bs-panel-icon] [bs-svg-icon] use{height:30px;width:30px}}[bs-panel~=trans] [bs-panel-content]{padding-left:68px}[bs-panel-content~=basic]{padding-left:27px;padding-right:27px;max-width:50em}@media only screen and (min-width:600px){[bs-panel-content~=basic]{padding-left:40.5px;padding-right:40.5px}}@media only screen and (min-width:1000px){[bs-skinny]{padding:54px 95px}}[bs-flush]{margin-bottom:0;border-bottom:0}[bs-list]{margin-left:0;list-style:none;word-wrap:break-word}[bs-list] p{margin-bottom:0}[bs-list] [bs-button-group]{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;margin-bottom:0}[bs-list] [bs-button-group] [bs-button]{height:auto;border:0;box-shadow:0 0 0 0;border-radius:0}[bs-list] [bs-button-group] [bs-button]:active{box-shadow:inset 0 0 1px rgba(0,0,0,.3)}[bs-list~=inline] li{display:inline-block}[bs-list~=bordered]>li{padding:11px 14px;border-bottom:1px solid #f0f0f0}[bs-list~=bordered]>li:first-child{border-top:1px solid #f0f0f0}[bs-list~=inline-controls]{word-wrap:break-word}[bs-list~=inline-controls] p{margin-bottom:7px}[bs-list~=inline-controls] li{background:#fff;position:relative;padding-left:14px;-webkit-transition:background .5s;transition:background .5s}[bs-list~=inline-controls] li:hover{background:#fbfbfb}[bs-list~=inline-controls] li:hover [bs-button~=subtle-alt]{color:#000}[bs-list~=inline-controls] li:hover [bs-button]{background:transparent}[bs-list~=inline-controls] li:hover [bs-button]:hover{color:#f54747}@media only screen and (min-width:750px){[bs-list~=inline-controls] li{padding:0;padding-left:14px;display:-webkit-box;display:-ms-flexbox;display:flex}[bs-list~=inline-controls] li p{margin-bottom:0;-webkit-box-flex:1;-ms-flex:1;flex:1;padding-top:11px;padding-bottom:11px}}[bs-list~=inline-controls] [bs-button-group]{margin-bottom:0}[bs-list~=inline-controls] [bs-button-group] [bs-button~=icon-left]{line-height:35px}[bs-list~=inline-controls] [bs-button-group] [bs-button~=icon-left] [bs-svg-icon]{top:12px}[bs-list~=inline-controls] [bs-button-group] [bs-svg-icon]{top:4px;width:22px;height:22px}[bs-tag]{position:absolute;right:calc(100% + 10px);text-transform:uppercase;font-size:10px;background:#f1f1f1;border-radius:3px;padding:1px 3px;top:6px;text-align:center}[bs-tag] span{color:#bebebe;display:block}[bs-tag~=offset]{top:44px}@media only screen and (min-width:600px){[bs-tag~=offset]{top:6px;right:auto;left:-86px}}[bs-list~=padded-left] li{padding-left:14px}[bs-list~=basic]{list-style:circle;margin-left:27px}[bs-offset~=basic]>li{padding-left:27px}@media only screen and (min-width:600px){[bs-offset~=basic]>li{padding-left:40.5px}}[bs-controls]{width:auto;-webkit-box-flex:1;-ms-flex:1;flex:1}[bs-flex~=top]{display:-webkit-box;display:-ms-flexbox;display:flex;background:#2c2c2c;border-bottom:1px solid #424242}@media only screen and (min-width:600px){[bs-flex~=top]{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;height:59px}}[bs-control]{font-size:12px;font-size:.66667rem;-webkit-box-flex:1;-ms-flex:1;flex:1;padding:10px 7px 6px;border-left:1px solid #333;border-top:1px solid #333;position:relative;color:#ababab;text-transform:uppercase;text-align:center}@media only screen and (min-width:600px){[bs-control]{-webkit-box-flex:0;-ms-flex:none;flex:none;height:100%;padding-top:10px;padding-left:14px;padding-right:14px}}[bs-control]:first-child{border-left-width:0}@media only screen and (min-width:600px){[bs-control]:first-child{border-left-width:1px}}[bs-control] [bs-svg-icon]{-webkit-transition:all .3s;transition:all .3s;width:14px;height:14px;top:0;display:block;margin-left:auto;margin-right:auto;margin-bottom:5px}@media only screen and (min-width:600px){[bs-control] [bs-svg-icon]{width:19px;height:19px}}[bs-control]:focus{text-decoration:none;color:#ababab}[bs-control]:hover{background:#444;text-decoration:none;color:#fff}[bs-control]:hover [bs-svg-icon]{-webkit-transform:rotate(1turn) scale(1.1);transform:rotate(1turn) scale(1.1);color:#fff}[bs-state~=success]{opacity:0;color:#81be00}[bs-state~=waiting]{opacity:0;color:#4a90e2}[bs-state-icons]{position:relative}[bs-state-icons] [bs-svg-icon]{position:absolute}[bs-anim~=spin]{-webkit-animation:a 1s infinite linear;animation:a 1s infinite linear}[bs-state-wrapper]{display:-webkit-box;display:-ms-flexbox;display:flex}[bs-state-wrapper] [bs-state~=inline]{top:3px;left:14px;width:17px;height:27px}[bs-state-wrapper].success [bs-state~=success],[bs-state-wrapper].waiting [bs-state~=waiting]{opacity:1}.cmn-toggle{position:absolute;margin-left:-9999px;visibility:hidden}.cmn-toggle+label{display:block;position:relative;cursor:pointer;outline:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background:#aaa}input.cmn-toggle-round+label{padding:4px;width:44px;height:22px;border-radius:3px}input.cmn-toggle-round+label:after,input.cmn-toggle-round+label:before{display:block;position:absolute;top:1px;left:2px;bottom:1px;content:""}input.cmn-toggle-round+label:before{right:2px;background-color:#aaa;border-radius:3px;-webkit-transition:background .2s;transition:background .2s}input.cmn-toggle-round+label:after{top:3px;width:16px;height:16px;background-color:#fff;border-radius:3px;-webkit-transition:margin .2s;transition:margin .2s}input.cmn-toggle-round:checked+label:before{background-color:#81be00}input.cmn-toggle-round+label:after{margin-left:1px}input.cmn-toggle-round:checked+label:after{margin-left:23px}input.cmn-toggle-round:checked+label{background-color:#81be00}[bs-footer]{color:#000;text-align:center;margin-bottom:27px;padding-top:27px;font-size:14px;font-size:.77778rem}@media only screen and (min-width:600px){[bs-footer]{padding-top:27px;position:fixed;bottom:0;width:240px;color:#ababab}}[bs-footer] p{margin-bottom:0}[bs-footer] a{color:#000}@media only screen and (min-width:600px){[bs-footer] a{color:#ababab}}[bs-footer] a:focus,[bs-footer] a:hover{text-decoration:none;color:#c5c5c5}[bs-footer] [bs-icon]{padding:0 10px}[bs-footer] [bs-svg-icon]{width:20px;height:20px}pre{margin-top:14px;padding:14px;border-radius:3px;box-shadow:inset -10px 0 10px #f0f0f0;border:1px solid #ebebeb}pre code{font-size:12px;font-size:.66667rem;font-size:16px;font-size:.88889rem;color:currentColor;line-height:1;background:transparent;border:0}code{background:#fbfbfb;display:inline-block;padding:0 5px;border:1px solid #f0f0f0;color:#2275d7;font-size:14px;font-size:.77778rem}[bs-notify]{position:absolute;left:0;width:100%;background:#444;color:#fff;text-align:center;padding:27px 14px;box-shadow:0 5px 5px 0 rgba(0,0,0,.2);-webkit-transform:translateY(-200%);transform:translateY(-200%);-webkit-transition:all .3s;transition:all .3s;z-index:5}[bs-notify].active{-webkit-transform:translateY(0);transform:translateY(0)}[bs-notify] p{margin-bottom:0}[bs-notify].error{background:#ed6a13}[bs-overlay]{position:absolute;width:100%;height:100%;top:0;left:0;right:0;background:rgba(0,0,0,.9);padding:54px 14px;color:#fff;text-align:center;visibility:hidden;z-index:6}[bs-overlay].active{visibility:visible}[bs-overlay] *{color:#fff}[bs-overlay] [bs-svg-icon]{width:40px;height:40px}@media only screen and (min-width:600px){[bs-overlay] [bs-svg-icon]{width:100px;height:100px}} -/*# sourceMappingURL=core.min.css.map */ diff --git a/web/node_modules/browser-sync-ui/public/css/core.min.css.map b/web/node_modules/browser-sync-ui/public/css/core.min.css.map deleted file mode 100644 index 68b5bce..0000000 --- a/web/node_modules/browser-sync-ui/public/css/core.min.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["modules/_reset.scss","vendor/_normalize.scss","core.css","vendor/_fonts.scss","theme/_animations.scss","theme/_base.scss","_vars.scss","modules/_mixins.scss","theme/_grid.scss","theme/_cloak.scss","theme/_header.scss","theme/_sidebar.scss","theme/_section-nav.scss","theme/_main-content.scss","theme/_svg.scss","theme/_custom-icons.scss","theme/_headings.scss","theme/_paragraphs.scss","theme/_links.scss","theme/_helpers.scss","theme/_buttons.scss","theme/_forms.scss","theme/_spinner.scss","theme/_panel.scss","theme/_lists.scss","theme/_top-bar.scss","theme/_state.scss","theme/_switch.scss","theme/_footer.scss","theme/_code.scss","theme/_notifications.scss","theme/_disconnect.scss"],"names":[],"mappings":"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h8BI,gBDhDQ,ACiDR,cDpEmB,ACqEnB,oBAAoB,CaevB,AlBm7BC,oDK/7BM,cDxEe,ACyEf,kBD3De,CC4DlB,ALg8BH,0BK77BM,eD1DI,CC2DP,AL87BH,2BK37BM,cDjFe,ACkFf,uCAAmC,AACnC,kBAAkB,CACrB,AL47BH,8BKz7BM,qBAAoB,AACpB,mBD1Ee,AC2Ef,aDxFe,CCyFlB,AL27BL,wBKl9BI,gBDhDQ,ACiDR,casB6B,AbrB7B,oBAAoB,CasBvB,AlB87BC,4DKj9BM,cakByB,AbjBzB,kBD3De,CC4DlB,ALk9BH,8BK/8BM,eD1DI,CC2DP,ALg9BH,+BK78BM,caSyB,AbRzB,uCAAmC,AACnC,kBAAkB,CACrB,AL88BH,kCK38BM,qBAAoB,AACpB,mBD1Ee,AC2Ef,aaCoD,CbAvD,AL68BL,wBKhgCI,ea2DuB,Ab1DvB,oBAAsB,Aa2DtB,iBdbe,Accf,gBAAiB,AACjB,WAAa,CAOhB,AlBi8BC,sCkBr8BM,QAAS,AACT,WAAY,AACZ,WAAa,CAChB,AlBu8BL,kBkB97BI,kBd9Be,Ac+Bf,kBd/Be,CcsClB,AlBy7BC,gCkB77BM,kBAAmB,AACnB,QAAS,AACT,SAAW,CACd,AlB+7BL,uBkBv7BI,kBAAmB,AACnB,iBAA2B,CAK9B,AlBo7BC,qCkBt7BM,SdjDW,CckDd,AlBw7BL,wBkBh7BI,kBAAmB,AACnB,kBAA4B,CAM/B,AlB46BC,sCkB/6BM,UAAW,AACX,Ud/DW,CcgEd,AlBi7BL,kBkBz6BI,oBAAA,AAAc,oBAAd,AAAc,aAAA,AACd,0BAAA,AAAqB,uBAArB,AAAqB,oBAAA,AACrB,kBd1Ee,CcwFlB,AlB65BC,8BkBx6BM,gBAAiB,AACjB,eAAiB,CASpB,AlBi6BD,0CkBx6BQ,2BAA4B,AAC5B,6BAA+B,CAClC,AlBy6BL,yCkBv6BQ,4BAA6B,AAC7B,8BAAgC,CACnC,AlBy6BT,oBkBn6BI,kBAAmB,AACnB,uBAAwB,AACxB,WdhKQ,AciKR,gBAAiB,AACjB,SAAU,AACV,yBAA0B,AAC1B,mBAAoB,AbjJpB,eakJuB,AbjJvB,oBAAsB,AakJtB,gBAAiB,AACjB,gBAAkB,CAoBrB,AlBk5BC,kCkBn6BM,gBAAkB,CACrB,AlBo6BH,0BkBj6BM,uBAAwB,AACxB,Ud/KI,CcgLP,AlBk6BH,0BkB/5BM,mBdzLe,Ac0Lf,UdpLI,CcqLP,AlBg6BH,2BkB75BM,mBAAkB,AAClB,kBAAoB,CACvB,AlB+5BL,mCkB15BQ,adxMe,CcyMlB,AlB45BL,gBkBv5BI,mBd5MmB,Ac6MnB,+BAA+B,CAKlC,AbxNO,yCL6mCJ,gBkBv5BI,iBdxIsB,Cc0I7B,CAAA,AbxNO,yCLqnCN,iDK/kCM,YAAc,CagMrB,CAAA,AC1ND,oBAfI,aAAc,AACd,sBAAuB,AACvB,kBfuFa,AetFb,UAAW,AACX,YARe,AASf,iBAA2B,AAC3B,mBf4Ee,Ae3Ef,eAAgB,AAChB,6DfyB4D,AexB5D,UfOQ,CeGX,AnBynCD,gBmBtnCI,WAAY,AACZ,SAAU,AACV,0BfdmB,AeenB,sBAAuB,AACvB,YfwDe,CenDlB,AnBmnCC,sBmBrnCM,afxBe,CeyBlB,AnBunCL,iBmBnnCI,oBAAA,AAAc,oBAAd,AAAc,aAAA,AACd,iBAA4B,CAsB/B,AnB+lCC,kCmBnnCM,gBAAkB,CACrB,AnBonCH,mCmBlnCM,mBAAA,AAAQ,WAAR,AAAQ,OAAA,AACR,qBAAA,AAA0B,kBAA1B,AAA0B,yBAAA,AAC1B,mBAAoB,AACpB,eAAiB,CAapB,AnBumCD,+CmBjnCQ,gBAAiB,AACjB,YAAa,AACb,cAAgB,CAOnB,AdpDD,yCLiqCA,+CmBjnCQ,iBf+BG,Ae9BH,YAAa,AACb,cAAgB,CAEvB,CAAA,AnBknCT,oBmB7mCI,kBAAmB,AACnB,kBfqBe,CehBlB,AnB0mCC,6BmB7mCM,WAAY,AACZ,aAAe,CAClB,AnB+mCL,mBmB5mCI,kBAAmB,AACnB,MAAO,AACP,MAAQ,CACX,AnB8mCD,iBKlpCI,ecwCuB,AdvCvB,oBAAsB,AcyCtB,kBAAmB,AACnB,cAAe,AACf,yBAA0B,AAC1B,gBAAkB,AAClB,cfzEmB,Ae0EnB,mBAAqB,CAKxB,AdpFO,yCL4rCJ,iBK5pCA,eckD2B,AdjD3B,mBAAsB,CcmDzB,CAAA,AnB4mCD,mBmBzmCI,Wf1EQ,Ae2ER,eAAkB,CACrB,AnB2mCD,WmBvmCI,UAAW,AACX,kBfRa,AeSb,WAAa,CA+BhB,AnB0kCC,amBtmCM,gBAAiB,AACjB,kBAAoB,CACvB,AnBumCH,iBmBnmCM,SAAU,AACV,gBAAiB,AACjB,UAAW,AACX,UAAW,Ad3Ef,ec4E2B,Ad3E3B,oBAAsB,Ac4ElB,gCftGe,Ce2GlB,AnBimCD,uBmBnmCQ,af9GW,Ce+Gd,AnBomCP,4BmBhmCM,UAAY,CACf,AnBimCH,2CmB7lCc,uBAAsB,CACzB,AnB+lCb,iBmBzlCI,WAAa,CAIhB,AnBulCC,uBmBzlCM,qBAAuB,CAC1B,AnB2lCL,mBmBllCI,oBAAA,AAAc,oBAAd,AAAc,aAAA,AACd,WAAa,CAmBhB,AnBikCC,qCmB/kCc,yBAA2B,CAC9B,AnBglCX,qBmB1kCM,gBAAiB,AACjB,kBAAoB,CAKvB,AnBukCD,gCmBzkCQ,iBf/EO,CegFV,ACrKT,qCAGI,gBhBiBU,AgBhBV,6CAAkD,AAClD,qCAA0C,AAC1C,UAAW,AACX,UAAY,CACf,AACD,6BAEI,kBAAmB,AACnB,MAAO,AACP,UAAY,CACf,AAED,eACI,WAAa,CAChB,AAED,QACI,UAAW,AACX,0BAAA,AAAmB,kBAAA,AACnB,oBAAqB,AACrB,gBAAiB,AACjB,kBAAmB,AACnB,eAAgB,AAChB,8BAAgC,AAChC,sBAAwB,AACxB,UAAW,AACX,QAAU,CAQb,AAlBD,eAYQ,SAAW,CACd,AAbL,cAeQ,UAAW,AACX,oCAAA,AAAqB,2BAAA,CACxB,AAEL,cACI,WAAY,AACZ,8BAAgC,AAChC,qBAAwB,CAC3B,AAED,qBACI,UAGI,oBhB7BM,AgB8BN,UAAY,CAAA,AAEhB,IACI,uBhBjCM,AgBkCN,UAAY,CAAA,CATpB,AASoB,aARhB,UAGI,oBhB7BM,AgB8BN,UAAY,CAAA,AAEhB,IACI,uBhBjCM,AgBkCN,UAAY,CAAA,CAAA,ApB4uCpB,WqB9xCI,kBAAmB,AA0BnB,gBjBZQ,AiBaR,oBjBsDe,AiBrDf,+BjBnBmB,CiBoBtB,ArBswCC,2BKjwCE,egB/B2B,AhBgC3B,qBAAsB,AgB5BlB,kBAAmB,AACnB,gBAAiB,AACjB,UjBMI,CiBLP,AhBRG,yCLwyCF,2BKxwCF,egB7B+B,AhB8B/B,oBAAsB,CgBzBrB,CAAA,ArBmyCH,+BqBhyCM,mBAAqB,CAMxB,ArB4xCD,oCqBhyCQ,yBAA0B,AAC1B,cjBPW,AiBQX,eAAiB,CACpB,ArBkyCT,4BqBlxCQ,kBjB1Be,CiB8BlB,ArBgxCH,wEqBlxCU,ajB7BW,CiB8Bd,ArBoxCT,sCqB/wCQ,kBAA2B,AAS3B,kBjB8BW,CiB7Bd,AhBlDG,yCL2zCJ,sCqB7wCQ,kBAA2B,CAIlC,ArB2wCC,sDqBjxCU,QAAkB,CACrB,CAAA,ArBmxCb,6CqB3wCQ,kBjB0BW,AiBzBX,mBjByBW,AiBxBX,cAAgB,CACnB,ArB6wCL,6CqB1wCQ,eAAgB,AAChB,gBAAiB,AACjB,cAAgB,CACnB,ArB4wCL,iBqBvwCI,gCjB5DmB,AiB6DnB,iBAAmB,CAYtB,ArB6vCC,uBqBtwCM,YAAa,AACb,WAAY,AACZ,WAAY,AACZ,cAAe,AACf,mBjBpEe,AiBqEf,kBAAmB,AACnB,YAAa,AACb,SAAW,CACd,ArBwwCL,qBqBpwCI,UAAW,AACX,mBjB9EmB,AiB+EnB,+BjB9EmB,CiB0FtB,AhBjGO,yCL41CJ,qBqBpwCI,ajBVsB,AiBWtB,mBjBVW,CiBkBlB,CAAA,AhBjGO,yCLg2CJ,kCqBlwCQ,kBjBfO,CiBiBd,CAAA,ArBmwCL,sBqB/vCI,eAAiB,CACpB,ArBiwCD,oBqB/vCI,+BjBhGmB,CiBiGtB,ArBiwCD,gBqB7vCI,kBAAmB,AACnB,UjB9Be,AiB+Bf,QAAkB,CAQrB,ArBuvCC,8BqB5vCM,WjBtHe,AiBuHf,YAAa,AACb,WAAY,AACZ,KAAO,CACV,ArB8vCL,mBqBzvCI,kBAA2B,AAC3B,kBjB5Ce,CiBmElB,AhBlJO,yCLu3CJ,mBqBxvCI,kBAA2B,CAmBlC,ArBuuCK,mCqBvvCM,UAAW,AACX,QjBrDkB,CiB8DrB,ArBmvCC,sGqBvvCU,YAAa,AACb,UAAY,CACf,CAAA,ArBwvCf,qCqBlvCM,iBAA2B,CAC9B,ArBovCL,0BqB/uCI,kBj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","file":"core.min.css","sourcesContent":["* {\n &,\n &:before,\n &:after{\n box-sizing: border-box;\n }\n}\n\nh1,h2,h3,h4,h5,h6,\np,blockquote,pre,\ndl,dd,ol,ul,\nform,fieldset,legend,\ntable,th,td,caption,\nhr{\n margin:0;\n padding:0;\n}\n\nabbr[title],dfn[title]{\n cursor:help;\n}\n\na,u,ins{\n text-decoration:none;\n}\n\nins{\n border-bottom:1px solid;\n}\n\nimg{\n font-style:italic;\n}\n\nlabel,\ninput,\ntextarea,\nbutton,\nselect,\noption{\n cursor:pointer;\n}\n .text-input:active,\n .text-input:focus,\n textarea:active,\n textarea:focus{\n cursor:text;\n outline:none;\n }\n\n","/*! normalize.css v3.0.1 | MIT License | git.io/normalize */\n\n/**\n * 1. Set default font family to sans-serif.\n * 2. Prevent iOS text size adjust after orientation change, without disabling\n * user zoom.\n */\n\nhtml {\n font-family: sans-serif; /* 1 */\n -ms-text-size-adjust: 100%; /* 2 */\n -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/**\n * Remove default margin.\n */\n\nbody {\n margin: 0;\n}\n\n/* HTML5 display definitions\n ========================================================================== */\n\n/**\n * Correct `block` display not defined for any HTML5 element in IE 8/9.\n * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.\n * Correct `block` display not defined for `main` in IE 11.\n */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n/**\n * 1. Correct `inline-block` display not defined in IE 8/9.\n * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n */\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; /* 1 */\n vertical-align: baseline; /* 2 */\n}\n\n/**\n * Prevent modern browsers from displaying `audio` without controls.\n * Remove excess height in iOS 5 devices.\n */\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n/**\n * Address `[hidden]` styling not present in IE 8/9/10.\n * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.\n */\n\n[hidden],\ntemplate {\n display: none;\n}\n\n/* Links\n ========================================================================== */\n\n/**\n * Remove the gray background color from active links in IE 10.\n */\n\na {\n background: transparent;\n}\n\n/**\n * Improve readability when focused and also mouse hovered in all browsers.\n */\n\na:active,\na:hover {\n outline: 0;\n}\n\n/* Text-level semantics\n ========================================================================== */\n\n/**\n * Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n */\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n/**\n * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n */\n\nb,\nstrong {\n font-weight: bold;\n}\n\n/**\n * Address styling not present in Safari and Chrome.\n */\n\ndfn {\n font-style: italic;\n}\n\n/**\n * Address variable `h1` font-size and margin within `section` and `article`\n * contexts in Firefox 4+, Safari, and Chrome.\n */\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n/**\n * Address styling not present in IE 8/9.\n */\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n/**\n * Address inconsistent and variable font size in all browsers.\n */\n\nsmall {\n font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` affecting `line-height` in all browsers.\n */\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n/* Embedded content\n ========================================================================== */\n\n/**\n * Remove border when inside `a` element in IE 8/9/10.\n */\n\nimg {\n border: 0;\n}\n\n/**\n * Correct overflow not hidden in IE 9/10/11.\n */\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n/* Grouping content\n ========================================================================== */\n\n/**\n * Address margin not present in IE 8/9 and Safari.\n */\n\nfigure {\n margin: 1em 40px;\n}\n\n/**\n * Address differences between Firefox and other browsers.\n */\n\nhr {\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n height: 0;\n}\n\n/**\n * Contain overflow in all browsers.\n */\n\npre {\n overflow: auto;\n}\n\n/**\n * Address odd `em`-unit font size rendering in all browsers.\n */\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n/* Forms\n ========================================================================== */\n\n/**\n * Known limitation: by default, Chrome and Safari on OS X allow very limited\n * styling of `select`, unless a `border` property is set.\n */\n\n/**\n * 1. Correct color not being inherited.\n * Known issue: affects color of disabled elements.\n * 2. Correct font properties not being inherited.\n * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; /* 1 */\n font: inherit; /* 2 */\n margin: 0; /* 3 */\n}\n\n/**\n * Address `overflow` set to `hidden` in IE 8/9/10/11.\n */\n\nbutton {\n overflow: visible;\n}\n\n/**\n * Address inconsistent `text-transform` inheritance for `button` and `select`.\n * All other form control elements do not inherit `text-transform` values.\n * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n * Correct `select` style inheritance in Firefox.\n */\n\nbutton,\nselect {\n text-transform: none;\n}\n\n/**\n * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n * and `video` controls.\n * 2. Correct inability to style clickable `input` types in iOS.\n * 3. Improve usability and consistency of cursor style between image-type\n * `input` and others.\n */\n\nbutton,\nhtml input[type=\"button\"], /* 1 */\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; /* 2 */\n cursor: pointer; /* 3 */\n}\n\n/**\n * Re-set default cursor for disabled elements.\n */\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n/**\n * Remove inner padding and border in Firefox 4+.\n */\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n/**\n * Address Firefox 4+ setting `line-height` on `input` using `!important` in\n * the UA stylesheet.\n */\n\ninput {\n line-height: normal;\n}\n\n/**\n * It's recommended that you don't attempt to style these elements.\n * Firefox's implementation doesn't respect box-sizing, padding, or width.\n *\n * 1. Address box sizing set to `content-box` in IE 8/9/10.\n * 2. Remove excess padding in IE 8/9/10.\n */\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; /* 1 */\n padding: 0; /* 2 */\n}\n\n/**\n * Fix the cursor style for Chrome's increment/decrement buttons. For certain\n * `font-size` values of the `input`, it causes the cursor style of the\n * decrement button to change from `default` to `text`.\n */\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n/**\n * 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n * 2. Address `box-sizing` set to `border-box` in Safari and Chrome\n * (include `-moz` to future-proof).\n */\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; /* 1 */\n -moz-box-sizing: content-box;\n -webkit-box-sizing: content-box; /* 2 */\n box-sizing: content-box;\n}\n\n/**\n * Remove inner padding and search cancel button in Safari and Chrome on OS X.\n * Safari (but not Chrome) clips the cancel button when the search input has\n * padding (and `textfield` appearance).\n */\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/**\n * Define consistent border, margin, and padding.\n */\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n/**\n * 1. Correct `color` not being inherited in IE 8/9/10/11.\n * 2. Remove padding so people aren't caught out if they zero out fieldsets.\n */\n\nlegend {\n border: 0; /* 1 */\n padding: 0; /* 2 */\n}\n\n/**\n * Remove default vertical scrollbar in IE 8/9/10/11.\n */\n\ntextarea {\n overflow: auto;\n}\n\n/**\n * Don't inherit the `font-weight` (applied by a rule above).\n * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n */\n\noptgroup {\n font-weight: bold;\n}\n\n/* Tables\n ========================================================================== */\n\n/**\n * Remove most spacing between table cells.\n */\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","*, *:before, *:after {\n box-sizing: border-box; }\n\nh1, h2, h3, h4, h5, h6,\np, blockquote, pre,\ndl, dd, ol, ul,\nform, fieldset, legend,\ntable, th, td, caption,\nhr {\n margin: 0;\n padding: 0; }\n\nabbr[title], dfn[title] {\n cursor: help; }\n\na, u, ins {\n text-decoration: none; }\n\nins {\n border-bottom: 1px solid; }\n\nimg {\n font-style: italic; }\n\nlabel,\ninput,\ntextarea,\nbutton,\nselect,\noption {\n cursor: pointer; }\n\n.text-input:active,\n.text-input:focus,\ntextarea:active,\ntextarea:focus {\n cursor: text;\n outline: none; }\n\n/*! normalize.css v3.0.1 | MIT License | git.io/normalize */\n/**\n * 1. Set default font family to sans-serif.\n * 2. Prevent iOS text size adjust after orientation change, without disabling\n * user zoom.\n */\nhtml {\n font-family: sans-serif;\n /* 1 */\n -ms-text-size-adjust: 100%;\n /* 2 */\n -webkit-text-size-adjust: 100%;\n /* 2 */ }\n\n/**\n * Remove default margin.\n */\nbody {\n margin: 0; }\n\n/* HTML5 display definitions\n ========================================================================== */\n/**\n * Correct `block` display not defined for any HTML5 element in IE 8/9.\n * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.\n * Correct `block` display not defined for `main` in IE 11.\n */\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n display: block; }\n\n/**\n * 1. Correct `inline-block` display not defined in IE 8/9.\n * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n */\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n /* 1 */\n vertical-align: baseline;\n /* 2 */ }\n\n/**\n * Prevent modern browsers from displaying `audio` without controls.\n * Remove excess height in iOS 5 devices.\n */\naudio:not([controls]) {\n display: none;\n height: 0; }\n\n/**\n * Address `[hidden]` styling not present in IE 8/9/10.\n * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.\n */\n[hidden],\ntemplate {\n display: none; }\n\n/* Links\n ========================================================================== */\n/**\n * Remove the gray background color from active links in IE 10.\n */\na {\n background: transparent; }\n\n/**\n * Improve readability when focused and also mouse hovered in all browsers.\n */\na:active,\na:hover {\n outline: 0; }\n\n/* Text-level semantics\n ========================================================================== */\n/**\n * Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n */\nabbr[title] {\n border-bottom: 1px dotted; }\n\n/**\n * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n */\nb,\nstrong {\n font-weight: bold; }\n\n/**\n * Address styling not present in Safari and Chrome.\n */\ndfn {\n font-style: italic; }\n\n/**\n * Address variable `h1` font-size and margin within `section` and `article`\n * contexts in Firefox 4+, Safari, and Chrome.\n */\nh1 {\n font-size: 2em;\n margin: 0.67em 0; }\n\n/**\n * Address styling not present in IE 8/9.\n */\nmark {\n background: #ff0;\n color: #000; }\n\n/**\n * Address inconsistent and variable font size in all browsers.\n */\nsmall {\n font-size: 80%; }\n\n/**\n * Prevent `sub` and `sup` affecting `line-height` in all browsers.\n */\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline; }\n\nsup {\n top: -0.5em; }\n\nsub {\n bottom: -0.25em; }\n\n/* Embedded content\n ========================================================================== */\n/**\n * Remove border when inside `a` element in IE 8/9/10.\n */\nimg {\n border: 0; }\n\n/**\n * Correct overflow not hidden in IE 9/10/11.\n */\nsvg:not(:root) {\n overflow: hidden; }\n\n/* Grouping content\n ========================================================================== */\n/**\n * Address margin not present in IE 8/9 and Safari.\n */\nfigure {\n margin: 1em 40px; }\n\n/**\n * Address differences between Firefox and other browsers.\n */\nhr {\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n height: 0; }\n\n/**\n * Contain overflow in all browsers.\n */\npre {\n overflow: auto; }\n\n/**\n * Address odd `em`-unit font size rendering in all browsers.\n */\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em; }\n\n/* Forms\n ========================================================================== */\n/**\n * Known limitation: by default, Chrome and Safari on OS X allow very limited\n * styling of `select`, unless a `border` property is set.\n */\n/**\n * 1. Correct color not being inherited.\n * Known issue: affects color of disabled elements.\n * 2. Correct font properties not being inherited.\n * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n */\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n /* 1 */\n font: inherit;\n /* 2 */\n margin: 0;\n /* 3 */ }\n\n/**\n * Address `overflow` set to `hidden` in IE 8/9/10/11.\n */\nbutton {\n overflow: visible; }\n\n/**\n * Address inconsistent `text-transform` inheritance for `button` and `select`.\n * All other form control elements do not inherit `text-transform` values.\n * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n * Correct `select` style inheritance in Firefox.\n */\nbutton,\nselect {\n text-transform: none; }\n\n/**\n * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n * and `video` controls.\n * 2. Correct inability to style clickable `input` types in iOS.\n * 3. Improve usability and consistency of cursor style between image-type\n * `input` and others.\n */\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n /* 2 */\n cursor: pointer;\n /* 3 */ }\n\n/**\n * Re-set default cursor for disabled elements.\n */\nbutton[disabled],\nhtml input[disabled] {\n cursor: default; }\n\n/**\n * Remove inner padding and border in Firefox 4+.\n */\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0; }\n\n/**\n * Address Firefox 4+ setting `line-height` on `input` using `!important` in\n * the UA stylesheet.\n */\ninput {\n line-height: normal; }\n\n/**\n * It's recommended that you don't attempt to style these elements.\n * Firefox's implementation doesn't respect box-sizing, padding, or width.\n *\n * 1. Address box sizing set to `content-box` in IE 8/9/10.\n * 2. Remove excess padding in IE 8/9/10.\n */\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n /* 1 */\n padding: 0;\n /* 2 */ }\n\n/**\n * Fix the cursor style for Chrome's increment/decrement buttons. For certain\n * `font-size` values of the `input`, it causes the cursor style of the\n * decrement button to change from `default` to `text`.\n */\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto; }\n\n/**\n * 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n * 2. Address `box-sizing` set to `border-box` in Safari and Chrome\n * (include `-moz` to future-proof).\n */\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n /* 1 */\n -moz-box-sizing: content-box;\n -webkit-box-sizing: content-box;\n /* 2 */\n box-sizing: content-box; }\n\n/**\n * Remove inner padding and search cancel button in Safari and Chrome on OS X.\n * Safari (but not Chrome) clips the cancel button when the search input has\n * padding (and `textfield` appearance).\n */\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none; }\n\n/**\n * Define consistent border, margin, and padding.\n */\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em; }\n\n/**\n * 1. Correct `color` not being inherited in IE 8/9/10/11.\n * 2. Remove padding so people aren't caught out if they zero out fieldsets.\n */\nlegend {\n border: 0;\n /* 1 */\n padding: 0;\n /* 2 */ }\n\n/**\n * Remove default vertical scrollbar in IE 8/9/10/11.\n */\ntextarea {\n overflow: auto; }\n\n/**\n * Don't inherit the `font-weight` (applied by a rule above).\n * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n */\noptgroup {\n font-weight: bold; }\n\n/* Tables\n ========================================================================== */\n/**\n * Remove most spacing between table cells.\n */\ntable {\n border-collapse: collapse;\n border-spacing: 0; }\n\ntd,\nth {\n padding: 0; }\n\n@font-face {\n font-family: 'source_sans';\n src: url(\"../fonts/source-sans/sourcesanspro-it-webfont.eot\");\n src: url(\"../fonts/source-sans/sourcesanspro-it-webfont.eot?#iefix\") format(\"embedded-opentype\"), url(\"../fonts/source-sans/sourcesanspro-it-webfont.woff2\") format(\"woff2\"), url(\"../fonts/source-sans/sourcesanspro-it-webfont.woff\") format(\"woff\"), url(\"../fonts/source-sans/sourcesanspro-it-webfont.ttf\") format(\"truetype\"), url(\"../fonts/source-sans/sourcesanspro-it-webfont.svg#source_sans_proitalic\") format(\"svg\");\n font-weight: normal;\n font-style: italic; }\n\n@font-face {\n font-family: 'source_sans';\n src: url(\"../fonts/source-sans/sourcesanspro-bold-webfont.eot\");\n src: url(\"../fonts/source-sans/sourcesanspro-bold-webfont.eot?#iefix\") format(\"embedded-opentype\"), url(\"../fonts/source-sans/sourcesanspro-bold-webfont.woff2\") format(\"woff2\"), url(\"../fonts/source-sans/sourcesanspro-bold-webfont.woff\") format(\"woff\"), url(\"../fonts/source-sans/sourcesanspro-bold-webfont.ttf\") format(\"truetype\"), url(\"../fonts/source-sans/sourcesanspro-bold-webfont.svg#source_sans_probold\") format(\"svg\");\n font-weight: bold;\n font-style: normal; }\n\n@font-face {\n font-family: 'source_sans';\n src: url(\"../fonts/source-sans/sourcesanspro-regular-webfont.eot\");\n src: url(\"../fonts/source-sans/sourcesanspro-regular-webfont.eot?#iefix\") format(\"embedded-opentype\"), url(\"../fonts/source-sans/sourcesanspro-regular-webfont.woff2\") format(\"woff2\"), url(\"../fonts/source-sans/sourcesanspro-regular-webfont.woff\") format(\"woff\"), url(\"../fonts/source-sans/sourcesanspro-regular-webfont.ttf\") format(\"truetype\"), url(\"../fonts/source-sans/sourcesanspro-regular-webfont.svg#source_sans_proregular\") format(\"svg\");\n font-weight: normal;\n font-style: normal; }\n\n[bs-anim~=\"spin\"] {\n animation: spin 1s infinite linear; }\n\n@keyframes spin {\n from {\n transform: rotate(0deg); }\n to {\n transform: rotate(360deg); } }\n\nhtml {\n overflow-x: hidden;\n overflow-y: auto;\n height: 100%;\n font: 112.5%/1.5 \"source_sans\", \"Lucida Grande\", \"Lucida Sans\", sans-serif;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n -webkit-font-smoothing: antialiased; }\n @media only screen and (min-width: 600px) {\n html {\n height: 100vh; } }\n\nbody {\n min-height: 100%;\n max-width: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n background: #fff;\n color: #777777;\n text-rendering: optimizeLegibility; }\n @media only screen and (min-width: 600px) {\n body {\n height: 100vh;\n overflow-y: hidden; } }\n\nmain {\n position: relative; }\n @media only screen and (min-width: 600px) {\n main {\n overflow: hidden; } }\n\nul ul,\nul ol,\nol ul,\nol ol,\ndl ul,\ndl ol {\n margin-bottom: 0; }\n\nul,\nol {\n margin-left: 27px; }\n\nul {\n list-style: disc; }\n ul ul {\n list-style: circle; }\n\nol {\n list-style: decimal; }\n ol ol {\n list-style: lower-alpha; }\n\ndt {\n font-weight: bold; }\n\ndd + dt {\n padding-top: 14px; }\n\ntable {\n margin-top: 14px;\n width: 100%; }\n\nth,\ntd {\n padding: 7px 14px;\n border-bottom: 1px solid #F0F0F0;\n text-align: left;\n vertical-align: top; }\n\nth {\n font-weight: bold; }\n\nthead tr:last-child th {\n border-bottom: 2px solid #F0F0F0; }\n\n[colspan] {\n text-align: center; }\n\n[colspan=\"1\"] {\n text-align: left; }\n\n[rowspan] {\n vertical-align: middle; }\n\n[rowspan=\"1\"] {\n vertical-align: top; }\n\nhr {\n clear: both;\n margin-bottom: 27px;\n border: none;\n border-bottom: 1px solid #F0F0F0;\n padding-bottom: 14px;\n height: 1px; }\n\n[bs-grid] {\n display: flex;\n width: 100%;\n flex-flow: wrap; }\n [bs-grid] > * {\n width: 100%;\n padding-top: 14px;\n padding-bottom: 7px; }\n\n@media only screen and (min-width: 750px) {\n [bs-grid~=\"desk-2\"] [bs-grid-item] {\n flex: 0 0 50%; } }\n\n@media only screen and (min-width: 1000px) {\n [bs-grid~=\"wide-4\"] [bs-grid-item] {\n flex: 0 0 25%; } }\n\n@media only screen and (min-width: 600px) {\n [bs-grid-item~=\"padded-right\"] {\n padding-right: 54px; } }\n\n[ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {\n display: none !important; }\n\n[bs-header] {\n position: relative;\n background: #222222; }\n @media only screen and (min-width: 600px) {\n [bs-header] {\n display: flex; } }\n [bs-header] [bs-header-row~=\"brand\"] {\n height: 60px; }\n [bs-header] [bs-header-row] {\n position: relative;\n width: 100%;\n display: flex; }\n [bs-header] [bs-header-row] * {\n margin-top: auto;\n margin-bottom: auto; }\n [bs-header] [bs-list~=\"header\"] {\n width: 100%;\n padding-left: 75px;\n font-size: 14px;\n font-size: 0.77778rem; }\n [bs-header] [bs-list~=\"header\"], [bs-header] [bs-list~=\"header\"] a {\n color: #fff; }\n [bs-header] [bs-list~=\"header\"]:hover, [bs-header] [bs-list~=\"header\"] a:hover {\n text-decoration: none; }\n [bs-header] [bs-list~=\"header\"] a {\n display: block;\n position: relative; }\n [bs-header] [bs-list~=\"header\"] a:hover {\n color: #81be00;\n text-shadow: 1px 1px 3px black; }\n\n[bs-toggle] {\n font-size: 24px;\n font-size: 1.33333rem;\n position: absolute;\n right: 0;\n cursor: pointer;\n width: 55px;\n text-align: center;\n height: 60px;\n line-height: 60px;\n color: #fff;\n transition: background .2s;\n text-shadow: 1px 1px 2px #00262C;\n border-left: 1px solid #222222;\n border-bottom: 1px solid #222222; }\n @media only screen and (min-width: 600px) {\n [bs-toggle] {\n display: none; } }\n [bs-toggle] svg {\n position: absolute;\n top: 14px;\n left: 12px;\n height: 30px;\n width: 30px;\n pointer-events: none; }\n [bs-toggle] svg[bs-state=alt] {\n opacity: 0; }\n [bs-toggle]:hover {\n background: #444444; }\n [bs-toggle].active svg {\n opacity: 0; }\n [bs-toggle].active svg[bs-state=alt] {\n opacity: 1 !important; }\n\n[bs-link~=\"version\"] {\n color: #777777;\n margin-left: 7px;\n font-size: 20px;\n font-size: 1.11111rem;\n position: relative;\n top: 4px; }\n [bs-link~=\"version\"]:hover, [bs-link~=\"version\"]:focus {\n color: #F54747; }\n\n[bs-sidebar] {\n position: relative;\n background: #444444; }\n @media only screen and (min-width: 600px) {\n [bs-sidebar] {\n width: 240px; }\n [bs-sidebar]:after {\n content: \" \";\n width: 10px;\n height: 100%;\n position: absolute;\n right: 0;\n top: 0;\n z-index: 10;\n background: linear-gradient(to right, transparent 0%, rgba(0, 0, 0, 0.2) 100%); } }\n\n[bs-section-nav] {\n background: #444444;\n position: absolute;\n width: 100%;\n transform: translateX(-200%) translateY(20px) scale(1.2);\n transition-timing-function: cubic-bezier(0.3, 0, 0, 1.3);\n transition: all .3s;\n opacity: 0;\n z-index: 5; }\n [bs-section-nav] ul {\n margin-bottom: 0; }\n [bs-section-nav] [bs-button] {\n text-transform: none;\n color: #ababab;\n width: 100%;\n border-radius: 0;\n text-align: left;\n border: 0;\n position: relative;\n background: transparent;\n display: block;\n height: auto;\n padding: 11px 0 11px 55px;\n border-bottom: 1px solid #363636;\n font-size: 16px;\n font-size: 0.88889rem;\n margin-bottom: 0;\n box-shadow: 0 0 0 0; }\n [bs-section-nav] [bs-button] [bs-svg-icon] {\n top: 14px;\n width: 20px;\n height: 20px; }\n [bs-section-nav] [bs-button].active {\n background: #363636;\n z-index: 5;\n color: #fff; }\n [bs-section-nav] [bs-button].active [bs-svg-icon] {\n color: #F54747; }\n [bs-section-nav] [bs-button]:hover {\n color: #fff;\n background: #363636; }\n [bs-section-nav] [bs-button]:active {\n color: #fff;\n box-shadow: 0px 1px 2px 0 rgba(0, 0, 0, 0.1) inset;\n background: #292929; }\n @media only screen and (min-width: 600px) {\n [bs-section-nav] {\n position: relative;\n transform: translateX(0) translateY(0) scale(1); }\n [bs-section-nav].ready {\n opacity: 1; } }\n [bs-section-nav].active {\n transform: translateX(0) translateY(0) scale(1);\n opacity: 1; }\n\n@media only screen and (min-width: 600px) {\n [bs-container] {\n display: flex; } }\n\n[bs-content] {\n overflow-x: hidden;\n height: auto;\n position: relative;\n background: #fff;\n width: 100%; }\n @media only screen and (min-width: 600px) {\n [bs-content] {\n height: 100vh;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n padding-bottom: 59px;\n margin-top: 1px;\n width: auto;\n flex: 1; } }\n\nsvg {\n width: 100%;\n height: 100%;\n opacity: 1;\n fill: currentColor !important;\n transition: .3s; }\n svg.icon-hidden {\n opacity: 0; }\n\n.icon {\n display: inline-block; }\n\n.icon-trash {\n width: 100%;\n max-width: 26px;\n height: 26px; }\n\n.icon-word {\n width: 100%;\n max-width: 150px;\n height: 100%;\n margin-left: 15px;\n color: #fff; }\n .icon-word svg {\n position: relative;\n top: -1px; }\n\n.icon-logo {\n color: #fff;\n transition: all .1s;\n width: 55px;\n height: 37px;\n text-align: center; }\n .icon-logo:hover {\n color: #fff;\n transform: scale(1.1); }\n\n[bs-svg-icon] {\n display: inline-block;\n width: 27px;\n height: 27px;\n line-height: inherit;\n position: relative;\n top: 7px; }\n [bs-svg-icon] use {\n width: 27px;\n height: 27px; }\n\nh1, h2, h3, h4, h5, h6, hgroup,\np, blockquote, address,\nul, ol, dl,\ntable,\nfieldset, figure, figcaption, details,\npre {\n margin-bottom: 14px; }\n\nh1, .h1,\nh2, .h2,\nh3, .h3,\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n color: #444444;\n font-weight: 400;\n line-height: 1;\n font-family: \"source_sans\", \"Lucida Grande\", \"Lucida Sans\", sans-serif;\n margin-bottom: 27px;\n -webkit-font-smoothing: antialiased; }\n h1 small, .h1 small,\n h2 small, .h2 small,\n h3 small, .h3 small,\n h4 small, .h4 small,\n h5 small, .h5 small,\n h6 small, .h6 small {\n font-size: inherit;\n font-weight: normal; }\n\nh1, .h1 {\n font-size: 36px;\n font-size: 2rem; }\n\nh2, .h2 {\n padding-top: 14px;\n font-size: 30px;\n font-size: 1.66667rem; }\n\nh3, .h3 {\n font-size: 18px;\n font-size: 1rem;\n font-weight: bold; }\n\nh4, .h4 {\n font-size: 16px;\n font-size: 0.88889rem; }\n\nh5, .h5 {\n font-size: 16px;\n font-size: 0.88889rem; }\n\nh6, .h6 {\n font-size: 16px;\n font-size: 0.88889rem; }\n\n[bs-heading] {\n background: #444444;\n font-size: 24px;\n font-size: 1.33333rem;\n padding-left: 55px;\n position: relative;\n line-height: 52px;\n margin-top: 0;\n margin-bottom: 0;\n color: #FBFBFB;\n background: #3f3f3f;\n border-top: 1px solid #3f3f3f; }\n @media only screen and (min-width: 600px) {\n [bs-heading] {\n font-size: 38px;\n font-size: 2.11111rem;\n color: #444444;\n background: #FBFBFB;\n padding-left: 80px;\n border-top: 0; }\n [bs-heading]:before {\n display: none; } }\n [bs-heading] [bs-svg-icon] {\n position: absolute;\n left: 14px;\n top: 11px; }\n @media only screen and (min-width: 600px) {\n [bs-heading] [bs-svg-icon] {\n height: 38px;\n width: 38px;\n top: 6px; } }\n\n.lede {\n font-size: 24px;\n font-size: 1.33333rem; }\n\n.small {\n font-size: 14px;\n font-size: 0.77778rem; }\n\na {\n color: #F54747;\n transition: background 0.3s ease, color 0.3s ease; }\n a:hover, a:active, a:focus {\n color: #000; }\n a [class^=\"icon-\"],\n a [class*=\" icon-\"] {\n text-decoration: none; }\n\n[bs-icon] {\n transition: background 0.3s ease, color 0.3s ease; }\n\n.flush--bottom {\n margin-bottom: 0 !important; }\n\n.text--cap {\n text-transform: capitalize; }\n\n.color--lime {\n color: #81be00; }\n\n.hidden {\n display: none; }\n .hidden.active {\n display: block; }\n\n[bs-stack] {\n margin-bottom: 14px; }\n\nspan.sep {\n margin-left: 5px;\n margin-right: 5px; }\n\n@media only screen and (min-width: 600px) {\n .width-100 {\n width: 100% !important; }\n .width-90 {\n width: 90% !important; }\n .width-80 {\n width: 80% !important; }\n .width-70 {\n width: 70% !important; }\n .width-60 {\n width: 60% !important; }\n .width-50 {\n width: 50% !important; }\n .width-40 {\n width: 40% !important; }\n .width-30 {\n width: 30% !important; }\n .width-20 {\n width: 20% !important; } }\n\n@media only screen and (min-width: 600px) {\n [bs-width~=\"100\"] {\n width: 100% !important; }\n [bs-width~=\"90\"] {\n width: 90% !important; }\n [bs-width~=\"80\"] {\n width: 80% !important; }\n [bs-width~=\"70\"] {\n width: 70% !important; }\n [bs-width~=\"60\"] {\n width: 60% !important; }\n [bs-width~=\"50\"] {\n width: 50% !important; }\n [bs-width~=\"40\"] {\n width: 40% !important; }\n [bs-width~=\"30\"] {\n width: 30% !important; }\n [bs-width~=\"25\"] {\n width: 25% !important; }\n [bs-width~=\"20\"] {\n width: 20% !important; }\n [bs-width~=\"10\"] {\n flex: 0 0 10% !important; }\n [bs-width~=\"5\"] {\n flex: 0 0 5% !important; } }\n\n[bs-text~=\"lede\"] {\n font-size: 18px;\n font-size: 1rem; }\n\n[bs-text~=\"mono\"] {\n font-weight: normal;\n font-size: 16px;\n font-size: 0.88889rem;\n font-family: monospace;\n color: #000; }\n\n[bs-text~=\"micro\"] {\n font-size: 12px;\n font-size: 0.66667rem;\n text-transform: uppercase;\n color: #d7d7d7;\n width: 60px;\n display: inline-block;\n text-align: right;\n margin-right: 5px; }\n\n[bs-color~=\"white\"] {\n color: #fff; }\n\n[bs-color~=\"success\"] {\n color: #81be00; }\n\n@media only screen and (min-width: 750px) {\n [bs-visible~=\"not-desk\"] {\n display: none; } }\n\n[bs-visible~=\"not-palm\"] {\n display: none !important; }\n @media only screen and (min-width: 600px) {\n [bs-visible~=\"not-palm\"] {\n display: inherit !important; } }\n\n@media only screen and (min-width: 600px) {\n [bs-visible~=\"palm\"] {\n display: none; } }\n\n[bs-sep] {\n color: #d7d7d7;\n margin-left: 3px;\n margin-right: 3px; }\n\n[bs-button] {\n font-size: 16px;\n font-size: 0.88889rem;\n display: inline-block;\n border: 1px solid #e30c0c;\n padding: 7px 21px;\n width: auto;\n vertical-align: middle;\n background: #F54747;\n color: #fff;\n border-radius: 3px;\n text-align: center;\n cursor: pointer;\n outline: none;\n transition: color .2s, background .2s;\n text-transform: uppercase;\n letter-spacing: 1px;\n margin-bottom: 14px;\n height: 40px;\n -webkit-tap-highlight-color: transparent; }\n [bs-button]:hover {\n text-decoration: none;\n color: #fff;\n background: #f21717; }\n [bs-button]:focus {\n text-decoration: none;\n color: #fff; }\n [bs-button]:active {\n color: #fff;\n box-shadow: 0px 1px 0px 0 rgba(0, 0, 0, 0.1) inset;\n text-shadow: 1px 1px 0px rgba(0, 0, 0, 0.4); }\n [bs-button].success {\n color: #81be00 !important; }\n [bs-button].success [bs-state~=\"success\"] {\n opacity: 1; }\n [bs-button].success [bs-state~=\"default\"] {\n opacity: 0; }\n [bs-button][disabled] {\n border-color: #d86464;\n background: #d86464;\n color: #F2AAAA; }\n [bs-button] [bs-svg-icon] {\n position: absolute;\n top: 11px;\n left: 14px;\n width: 16px;\n height: 16px; }\n\n[bs-button~=\"subtle\"] {\n background: #fff;\n color: #F54747;\n border-color: #e3e3e3; }\n [bs-button~=\"subtle\"]:hover, [bs-button~=\"subtle\"]:focus {\n color: #F54747;\n background: #F0F0F0; }\n [bs-button~=\"subtle\"]:focus {\n background: #fff; }\n [bs-button~=\"subtle\"]:active {\n color: #F54747;\n text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2);\n background: #f7f7f7; }\n [bs-button~=\"subtle\"][disabled] {\n border-color: #e3e3e3;\n background: #F0F0F0;\n color: #F2AAAA; }\n\n[bs-button~=\"subtle-alt\"] {\n background: #fff;\n color: #8a8a8a;\n border-color: #e3e3e3; }\n [bs-button~=\"subtle-alt\"]:hover, [bs-button~=\"subtle-alt\"]:focus {\n color: #8a8a8a;\n background: #F0F0F0; }\n [bs-button~=\"subtle-alt\"]:focus {\n background: #fff; }\n [bs-button~=\"subtle-alt\"]:active {\n color: #8a8a8a;\n text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2);\n background: #f7f7f7; }\n [bs-button~=\"subtle-alt\"][disabled] {\n border-color: #e3e3e3;\n background: #F0F0F0;\n color: #bdbdbd; }\n\n[bs-button~=\"size-small\"] {\n font-size: 14px;\n font-size: 0.77778rem;\n padding: 5px 14px;\n padding-top: 7px;\n height: 34px; }\n [bs-button~=\"size-small\"] [bs-svg-icon] {\n top: 9px;\n width: 14px;\n height: 14px; }\n\n[bs-button~=\"icon\"] {\n padding-left: 14px;\n padding-right: 14px; }\n [bs-button~=\"icon\"] [bs-svg-icon] {\n position: relative;\n top: 2px;\n left: auto; }\n\n[bs-button~=\"icon-left\"] {\n position: relative;\n padding-left: 41px; }\n [bs-button~=\"icon-left\"] [bs-svg-icon] {\n left: 14px; }\n\n[bs-button~=\"icon-right\"] {\n position: relative;\n padding-right: 41px; }\n [bs-button~=\"icon-right\"] [bs-svg-icon] {\n left: auto;\n right: 14px; }\n\n[bs-button-group] {\n display: flex;\n align-items: stretch;\n margin-bottom: 14px; }\n [bs-button-group] [bs-button] {\n border-radius: 0;\n margin-bottom: 0; }\n [bs-button-group] [bs-button]:first-child {\n border-top-left-radius: 3px;\n border-bottom-left-radius: 3px; }\n [bs-button-group] [bs-button]:last-child {\n border-top-right-radius: 3px;\n border-bottom-right-radius: 3px; }\n\n[bs-button~=\"inline\"] {\n position: relative;\n background: transparent;\n color: #000;\n border-radius: 0;\n border: 0;\n text-transform: uppercase;\n box-shadow: 0 0 0 0;\n font-size: 14px;\n font-size: 0.77778rem;\n margin-bottom: 0;\n padding-top: 10px; }\n [bs-button~=\"inline\"] [bs-checkbox] {\n margin-right: 8px; }\n [bs-button~=\"inline\"]:focus {\n background: transparent;\n color: #000; }\n [bs-button~=\"inline\"]:hover {\n background: #F0F0F0;\n color: #000; }\n [bs-button~=\"inline\"]:active {\n background: #d7d7d7;\n box-shadow: 0 0 0 0; }\n\n[bs-button~=\"success\"] [bs-svg-icon] {\n color: #81be00; }\n\n[bs-button-row] {\n background: #FBFBFB;\n border-bottom: 1px solid #d7d7d7; }\n @media only screen and (min-width: 600px) {\n [bs-button-row] {\n padding-left: 27px; } }\n\n@media only screen and (min-width: 600px) {\n [bs-action~=\"menu-toggle\"] {\n display: none; } }\n\n@media only screen and (min-width: 600px) {\n [bs-action~=\"menu-close\"] {\n display: none; } }\n\n/*\n * Basic Inputs\n */\nbutton,\ninput,\nselect {\n outline: none;\n vertical-align: middle;\n border-radius: 3px;\n outline: 0;\n height: 40px;\n padding-left: 7px;\n padding-right: 14px;\n max-width: 100%;\n font-family: \"source_sans\", \"Lucida Grande\", \"Lucida Sans\", sans-serif;\n color: #000; }\n\n[bs-code-input] {\n width: 100%;\n border: 0;\n border: 1px dashed #F0F0F0;\n font-family: monospace;\n padding: 14px; }\n [bs-code-input]:focus {\n color: #4A90E2; }\n\n[bs-heading-bar] {\n display: flex;\n margin-bottom: 7px; }\n [bs-heading-bar] [bs-input-label] {\n line-height: 36px; }\n [bs-heading-bar] [bs-button-group] {\n flex: 1;\n justify-content: flex-end;\n margin-bottom: auto;\n margin-top: auto; }\n [bs-heading-bar] [bs-button-group] [bs-button] {\n padding: 3px 5px;\n height: 24px;\n font-size: 10px; }\n @media only screen and (min-width: 600px) {\n [bs-heading-bar] [bs-button-group] [bs-button] {\n padding: 7px 14px;\n height: 34px;\n font-size: 14px; } }\n\n[bs-textarea-input] {\n position: relative;\n margin-bottom: 14px; }\n [bs-textarea-input] [bs-tag] {\n left: -64px;\n color: #D08989; }\n\n[bs-error~=\"offset\"] {\n position: absolute;\n top: 0;\n left: 0; }\n\n[bs-input-label] {\n font-size: 14px;\n font-size: 0.77778rem;\n position: relative;\n display: block;\n text-transform: uppercase;\n font-weight: bold;\n color: #ababab;\n letter-spacing: .5px; }\n @media only screen and (min-width: 600px) {\n [bs-input-label] {\n font-size: 14px;\n font-size: 0.77778rem; } }\n\n[bs-label-heading] {\n color: #000;\n font-weight: bold; }\n\n[bs-input] {\n padding: 0;\n border-radius: 3px;\n height: 100%; }\n [bs-input] > * {\n margin-top: auto;\n margin-bottom: auto; }\n [bs-input] input {\n border: 0;\n border-radius: 0;\n padding: 0;\n outline: 0;\n font-size: 16px;\n font-size: 0.88889rem;\n border-bottom: 1px dashed #F0F0F0; }\n [bs-input] input:focus {\n color: #4A90E2; }\n [bs-input] input[type=text] {\n width: 100%; }\n [bs-input] input[type=radio]:checked + label {\n color: #4A90E2 !important; }\n\n[bs-input~=\"text\"] {\n height: auto; }\n [bs-input~=\"text\"] input {\n font-family: monospace; }\n\n[bs-input~=\"inline\"] {\n display: flex;\n height: auto; }\n [bs-input~=\"inline\"] input:focus + label {\n text-decoration: underline; }\n [bs-input~=\"inline\"] > * {\n margin-top: auto;\n margin-bottom: auto; }\n [bs-input~=\"inline\"] > *:first-child {\n margin-right: 14px; }\n\n.loader,\n.loader:before,\n.loader:after {\n background: #333333;\n -webkit-animation: load1 .5s infinite ease-in-out;\n animation: load1 .5s infinite ease-in-out;\n width: 1em;\n height: 2em; }\n\n.loader:before,\n.loader:after {\n position: absolute;\n top: 0;\n content: ''; }\n\n.loader:before {\n left: -1.5em; }\n\n.loader {\n opacity: 1;\n transition: all 1s;\n text-indent: -9999em;\n margin: 8em auto;\n position: absolute;\n font-size: 11px;\n -webkit-animation-delay: -0.16s;\n animation-delay: -0.16s;\n z-index: 1;\n left: 50%; }\n .loader.behind {\n z-index: 0; }\n .loader.ready {\n opacity: 0;\n transform: translateY(-200%); }\n\n.loader:after {\n left: 1.5em;\n -webkit-animation-delay: -0.32s;\n animation-delay: -0.32s; }\n\n@keyframes load1 {\n 0%,\n 80%,\n 100% {\n box-shadow: 0 0 #333333;\n height: 4em; }\n 40% {\n box-shadow: 0 -2em #333333;\n height: 5em; } }\n\n[bs-panel] {\n position: relative;\n background: #fff;\n padding: 27px 0 14px;\n border-bottom: 1px solid #F0F0F0; }\n [bs-panel] [bs-text~=\"lede\"] {\n font-size: 20px;\n font-size: 1.11111rem;\n position: relative;\n margin-bottom: 0;\n color: #000; }\n @media only screen and (min-width: 600px) {\n [bs-panel] [bs-text~=\"lede\"] {\n font-size: 24px;\n font-size: 1.33333rem; } }\n [bs-panel] [bs-text~=\"prefixed\"] {\n text-transform: none; }\n [bs-panel] [bs-text~=\"prefixed\"] span {\n text-transform: uppercase;\n color: #F0F0F0;\n font-weight: 200; }\n\n[bs-panel~=\"switch\"].disabled {\n background: #FBFBFB; }\n [bs-panel~=\"switch\"].disabled, [bs-panel~=\"switch\"].disabled [bs-text~=\"lede\"] {\n color: #ababab; }\n\n[bs-panel~=\"switch\"] [bs-panel-content] {\n padding-left: 81px;\n margin-bottom: 14px; }\n @media only screen and (min-width: 600px) {\n [bs-panel~=\"switch\"] [bs-panel-content] {\n padding-left: 108px; }\n [bs-panel~=\"switch\"] [bs-panel-content] [bs-panel-icon] {\n top: 33px; } }\n\n[bs-panel~=\"switch\"] [bs-panel-content~=\"basic\"] {\n padding-left: 14px;\n padding-right: 14px;\n max-width: none; }\n\n[bs-panel~=\"switch\"] [bs-panel-content~=\"tight\"] {\n padding-left: 0;\n padding-right: 0;\n max-width: none; }\n\n[bs-panel~=\"last\"] {\n border-bottom: 2px solid #F0F0F0;\n position: relative; }\n [bs-panel~=\"last\"]:after {\n content: \" \";\n width: 100%;\n height: 1px;\n display: block;\n background: #F0F0F0;\n position: absolute;\n bottom: -4px;\n z-index: 2; }\n\n[bs-panel~=\"controls\"] {\n padding: 0;\n background: #FBFBFB;\n border-bottom: 1px solid #F0F0F0; }\n @media only screen and (min-width: 600px) {\n [bs-panel~=\"controls\"] {\n padding: 27px;\n padding-bottom: 14px; } }\n @media only screen and (min-width: 600px) {\n [bs-panel~=\"controls\"] [bs-heading] {\n margin-bottom: 14px; } }\n\n[bs-panel~=\"no-border\"] {\n border-bottom: 0; }\n\n[bs-panel~=\"outline\"] {\n border-bottom: 1px solid #F0F0F0; }\n\n[bs-panel-icon] {\n position: absolute;\n left: 14px;\n top: 30px; }\n [bs-panel-icon] [bs-svg-icon] {\n color: #444444;\n height: 24px;\n width: 24px;\n top: 0; }\n\n[bs-panel-content] {\n padding-left: 54px;\n padding-right: 14px; }\n @media only screen and (min-width: 600px) {\n [bs-panel-content] {\n padding-left: 108px; }\n [bs-panel-content] [bs-panel-icon] {\n left: 44px;\n top: 27px; }\n [bs-panel-content] [bs-panel-icon] [bs-svg-icon] {\n height: 30px;\n width: 30px; }\n [bs-panel-content] [bs-panel-icon] [bs-svg-icon] use {\n height: 30px;\n width: 30px; } }\n [bs-panel~=\"trans\"] [bs-panel-content] {\n padding-left: 68px; }\n\n[bs-panel-content~=\"basic\"] {\n padding-left: 27px;\n padding-right: 27px;\n max-width: 50em; }\n @media only screen and (min-width: 600px) {\n [bs-panel-content~=\"basic\"] {\n padding-left: 40.5px;\n padding-right: 40.5px; } }\n\n@media only screen and (min-width: 1000px) {\n [bs-skinny] {\n padding: 54px 95px; } }\n\n[bs-flush] {\n margin-bottom: 0;\n border-bottom: 0; }\n\n[bs-list] {\n margin-left: 0;\n list-style: none;\n word-wrap: break-word; }\n [bs-list] p {\n margin-bottom: 0; }\n [bs-list] [bs-button-group] {\n justify-content: flex-end;\n margin-bottom: 0; }\n [bs-list] [bs-button-group] [bs-button] {\n height: auto;\n border: 0;\n box-shadow: 0 0 0 0;\n border-radius: 0; }\n [bs-list] [bs-button-group] [bs-button]:active {\n box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.3) inset; }\n\n[bs-list~=\"inline\"] li {\n display: inline-block; }\n\n[bs-list~=\"bordered\"] > li {\n padding: 11px 14px;\n border-bottom: 1px solid #F0F0F0; }\n [bs-list~=\"bordered\"] > li:first-child {\n border-top: 1px solid #F0F0F0; }\n\n[bs-list~=\"inline-controls\"] {\n word-wrap: break-word; }\n [bs-list~=\"inline-controls\"] p {\n margin-bottom: 7px; }\n [bs-list~=\"inline-controls\"] li {\n background: #fff;\n position: relative;\n padding-left: 14px;\n transition: background .5s; }\n [bs-list~=\"inline-controls\"] li:hover {\n background: #FBFBFB; }\n [bs-list~=\"inline-controls\"] li:hover [bs-button~=\"subtle-alt\"] {\n color: #000; }\n [bs-list~=\"inline-controls\"] li:hover [bs-button] {\n background: transparent; }\n [bs-list~=\"inline-controls\"] li:hover [bs-button]:hover {\n color: #F54747; }\n @media only screen and (min-width: 750px) {\n [bs-list~=\"inline-controls\"] li {\n padding: 0;\n padding-left: 14px;\n display: flex; }\n [bs-list~=\"inline-controls\"] li p {\n margin-bottom: 0;\n flex: 1;\n padding-top: 11px;\n padding-bottom: 11px; } }\n [bs-list~=\"inline-controls\"] [bs-button-group] {\n margin-bottom: 0; }\n [bs-list~=\"inline-controls\"] [bs-button-group] [bs-button~=\"icon-left\"] {\n line-height: 35px; }\n [bs-list~=\"inline-controls\"] [bs-button-group] [bs-button~=\"icon-left\"] [bs-svg-icon] {\n top: 12px; }\n [bs-list~=\"inline-controls\"] [bs-button-group] [bs-svg-icon] {\n top: 4px;\n width: 22px;\n height: 22px; }\n\n[bs-tag] {\n position: absolute;\n right: calc(100% + 10px);\n text-transform: uppercase;\n font-size: 10px;\n background: #f1f1f1;\n border-radius: 3px;\n padding: 1px 3px;\n top: 6px;\n text-align: center; }\n [bs-tag] span {\n color: #bebebe;\n display: block; }\n\n[bs-tag~=\"offset\"] {\n top: 44px; }\n @media only screen and (min-width: 600px) {\n [bs-tag~=\"offset\"] {\n top: 6px;\n right: auto;\n left: -86px; } }\n\n[bs-list~=\"padded-left\"] li {\n padding-left: 14px; }\n\n[bs-list~=\"basic\"] {\n list-style: circle;\n margin-left: 27px; }\n\n[bs-offset~=\"basic\"] > li {\n padding-left: 27px; }\n @media only screen and (min-width: 600px) {\n [bs-offset~=\"basic\"] > li {\n padding-left: 40.5px; } }\n\n[bs-controls] {\n width: auto;\n flex: 1; }\n\n[bs-flex~=\"top\"] {\n display: flex;\n background: #2c2c2c;\n border-bottom: 1px solid #424242; }\n @media only screen and (min-width: 600px) {\n [bs-flex~=\"top\"] {\n justify-content: flex-end;\n height: 59px; } }\n\n[bs-control] {\n font-size: 12px;\n font-size: 0.66667rem;\n flex: 1;\n padding-left: 7px;\n padding-right: 7px;\n border-left: 1px solid #333333;\n border-top: 1px solid #333333;\n position: relative;\n color: #ababab;\n text-transform: uppercase;\n text-align: center;\n padding-top: 10px;\n padding-bottom: 6px; }\n @media only screen and (min-width: 600px) {\n [bs-control] {\n flex: none;\n height: 100%;\n padding-top: 10px;\n padding-left: 14px;\n padding-right: 14px; } }\n [bs-control]:first-child {\n border-left-width: 0; }\n @media only screen and (min-width: 600px) {\n [bs-control]:first-child {\n border-left-width: 1px; } }\n [bs-control] [bs-svg-icon] {\n transition: all .3s;\n width: 14px;\n height: 14px;\n top: 0;\n display: block;\n margin-left: auto;\n margin-right: auto;\n margin-bottom: 5px; }\n @media only screen and (min-width: 600px) {\n [bs-control] [bs-svg-icon] {\n width: 19px;\n height: 19px; } }\n [bs-control]:focus {\n text-decoration: none;\n color: #ababab; }\n [bs-control]:hover {\n background: #444444;\n text-decoration: none;\n color: #fff; }\n [bs-control]:hover [bs-svg-icon] {\n transform: rotate(360deg) scale(1.1);\n color: #fff; }\n\n[bs-state~=\"success\"] {\n opacity: 0;\n color: #81be00; }\n\n[bs-state~=\"waiting\"] {\n opacity: 0;\n color: #4A90E2; }\n\n[bs-state-icons] {\n position: relative; }\n [bs-state-icons] [bs-svg-icon] {\n position: absolute; }\n\n[bs-anim~=\"spin\"] {\n animation: spin 1s infinite linear; }\n\n[bs-state-wrapper] {\n display: flex; }\n [bs-state-wrapper] [bs-state~=\"inline\"] {\n top: 3px;\n left: 14px;\n width: 17px;\n height: 27px; }\n [bs-state-wrapper].waiting [bs-state~=\"waiting\"] {\n opacity: 1; }\n [bs-state-wrapper].success [bs-state~=\"success\"] {\n opacity: 1; }\n\n.cmn-toggle {\n position: absolute;\n margin-left: -9999px;\n visibility: hidden; }\n\n.cmn-toggle + label {\n display: block;\n position: relative;\n cursor: pointer;\n outline: none;\n user-select: none;\n background: #AAAAAA; }\n\ninput.cmn-toggle-round + label {\n padding: 4px;\n width: 44px;\n height: 22px;\n border-radius: 3px; }\n\ninput.cmn-toggle-round + label:before, input.cmn-toggle-round + label:after {\n display: block;\n position: absolute;\n top: 1px;\n left: 2px;\n bottom: 1px;\n content: \"\"; }\n\ninput.cmn-toggle-round + label:before {\n right: 2px;\n background-color: #AAAAAA;\n border-radius: 3px;\n transition: background 0.2s; }\n\ninput.cmn-toggle-round + label:after {\n top: 3px;\n width: 16px;\n height: 16px;\n background-color: #fff;\n border-radius: 3px;\n transition: margin 0.2s; }\n\ninput.cmn-toggle-round:checked + label:before {\n background-color: #81be00; }\n\ninput.cmn-toggle-round + label:after {\n margin-left: 1px; }\n\ninput.cmn-toggle-round:checked + label:after {\n margin-left: 23px; }\n\ninput.cmn-toggle-round:checked + label {\n background-color: #81be00; }\n\n[bs-footer] {\n color: #000;\n text-align: center;\n margin-bottom: 27px;\n padding-top: 27px;\n font-size: 14px;\n font-size: 0.77778rem; }\n @media only screen and (min-width: 600px) {\n [bs-footer] {\n padding-top: 27px;\n position: fixed;\n bottom: 0;\n width: 240px;\n color: #ababab; } }\n [bs-footer] p {\n margin-bottom: 0; }\n [bs-footer] a {\n color: #000; }\n @media only screen and (min-width: 600px) {\n [bs-footer] a {\n color: #ababab; } }\n [bs-footer] a:hover, [bs-footer] a:focus {\n text-decoration: none;\n color: #c5c5c5; }\n [bs-footer] [bs-icon] {\n padding: 0 10px; }\n [bs-footer] [bs-svg-icon] {\n width: 20px;\n height: 20px; }\n\npre {\n margin-top: 14px;\n padding: 14px;\n border-radius: 3px;\n box-shadow: -10px 0px 10px #F0F0F0 inset;\n border: 1px solid #ebebeb; }\n pre code {\n font-size: 12px;\n font-size: 0.66667rem;\n font-size: 16px;\n font-size: 0.88889rem;\n color: currentColor;\n line-height: 1;\n background: transparent;\n border: 0; }\n\ncode {\n background: #FBFBFB;\n display: inline-block;\n padding: 0 5px;\n border: 1px solid #F0F0F0;\n color: #2275d7;\n font-size: 14px;\n font-size: 0.77778rem; }\n\n[bs-notify] {\n position: absolute;\n left: 0;\n width: 100%;\n background: #444444;\n color: #fff;\n text-align: center;\n padding: 27px 14px;\n box-shadow: 0 5px 5px 0px rgba(0, 0, 0, 0.2);\n transform: translateY(-200%);\n transition: all .3s;\n z-index: 100; }\n [bs-notify].active {\n transform: translateY(0); }\n [bs-notify] p {\n margin-bottom: 0; }\n [bs-notify].error {\n background: #ED6A13; }\n\n[bs-overlay] {\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.9);\n padding: 54px 14px;\n color: #fff;\n text-align: center;\n visibility: hidden;\n z-index: 2000; }\n [bs-overlay].active {\n visibility: visible; }\n [bs-overlay] * {\n color: #fff; }\n [bs-overlay] [bs-svg-icon] {\n width: 40px;\n height: 40px; }\n @media only screen and (min-width: 600px) {\n [bs-overlay] [bs-svg-icon] {\n width: 100px;\n height: 100px; } }\n","$source-path: \"../fonts/source-sans\";\n\n@font-face {\n font-family: 'source_sans';\n src: url('#{$source-path}/sourcesanspro-it-webfont.eot');\n src: url('#{$source-path}/sourcesanspro-it-webfont.eot?#iefix') format('embedded-opentype'),\n url('#{$source-path}/sourcesanspro-it-webfont.woff2') format('woff2'),\n url('#{$source-path}/sourcesanspro-it-webfont.woff') format('woff'),\n url('#{$source-path}/sourcesanspro-it-webfont.ttf') format('truetype'),\n url('#{$source-path}/sourcesanspro-it-webfont.svg#source_sans_proitalic') format('svg');\n font-weight: normal;\n font-style: italic;\n}\n\n@font-face {\n font-family: 'source_sans';\n src: url('#{$source-path}/sourcesanspro-bold-webfont.eot');\n src: url('#{$source-path}/sourcesanspro-bold-webfont.eot?#iefix') format('embedded-opentype'),\n url('#{$source-path}/sourcesanspro-bold-webfont.woff2') format('woff2'),\n url('#{$source-path}/sourcesanspro-bold-webfont.woff') format('woff'),\n url('#{$source-path}/sourcesanspro-bold-webfont.ttf') format('truetype'),\n url('#{$source-path}/sourcesanspro-bold-webfont.svg#source_sans_probold') format('svg');\n font-weight: bold;\n font-style: normal;\n\n}\n\n@font-face {\n font-family: 'source_sans';\n src: url('#{$source-path}/sourcesanspro-regular-webfont.eot');\n src: url('#{$source-path}/sourcesanspro-regular-webfont.eot?#iefix') format('embedded-opentype'),\n url('#{$source-path}/sourcesanspro-regular-webfont.woff2') format('woff2'),\n url('#{$source-path}/sourcesanspro-regular-webfont.woff') format('woff'),\n url('#{$source-path}/sourcesanspro-regular-webfont.ttf') format('truetype'),\n url('#{$source-path}/sourcesanspro-regular-webfont.svg#source_sans_proregular') format('svg');\n font-weight: normal;\n font-style: normal;\n}\n","\n[bs-anim~=\"spin\"] {\n animation: spin 1s infinite linear;\n}\n\n@keyframes spin {\n from {transform:rotate(0deg);}\n to {transform:rotate(360deg);}\n}","html {\n overflow-x: hidden;\n overflow-y: auto;\n height: 100%;\n font: #{($base-font-size/16px)*100%}/#{$base-line-height} $base-font-family;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n -webkit-font-smoothing: antialiased;\n\n @include media-query(min, $lap-start) {\n height: 100vh;\n }\n\n}\n\nbody {\n min-height: 100%;\n max-width: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n background: $white;\n color: $body-text;\n text-rendering: optimizeLegibility;\n\n @include media-query(min, $lap-start) {\n height: 100vh;\n overflow-y: hidden;\n }\n}\n\nmain {\n position: relative;\n @include media-query(min, $lap-start) {\n overflow: hidden;\n }\n}\n\n\n// Lists\n\nul,\nol,\ndl {\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\nul,\nol {\n margin-left: $base-spacing;\n}\n\nul {\n list-style: disc;\n\n ul {\n list-style: circle;\n }\n}\n\nol {\n list-style: decimal;\n\n ol {\n list-style: lower-alpha;\n }\n}\n\ndt {\n font-weight: bold;\n}\n\ndd + dt {\n padding-top: $half-spacing;\n}\n\n\n// Tables\n\ntable {\n margin-top: $half-spacing;\n width: 100%;\n}\n\nth,\ntd {\n padding: $half-spacing/2 $half-spacing;\n border-bottom: 1px solid $grey-border;\n text-align: left;\n vertical-align: top;\n}\n\nth {\n font-weight: bold;\n}\n\nthead {\n tr:last-child {\n th {\n border-bottom: 2px solid $grey-border;\n }\n }\n}\n\n[colspan] {\n text-align: center;\n}\n\n[colspan=\"1\"] {\n text-align: left;\n}\n\n[rowspan] {\n vertical-align: middle;\n}\n\n[rowspan=\"1\"] {\n vertical-align: top;\n}\n\n\n// table {\n// tr {\n// td:first-child {\n// white-space: nowrap;\n// font-weight: bold;\n// }\n// }\n// td {\n// padding: $half-spacing $half-spacing/2 ;\n// }\n// tbody {\n// tr:nth-child(odd) {\n// background: #fafafa;\n// }\n// }\n// }\n\n\n// Sectioning\n\nhr {\n clear: both;\n margin-bottom: $base-spacing;\n border: none;\n border-bottom: 1px solid $grey-border;\n padding-bottom: $half-spacing;\n height: 1px;\n}\n","$red: #F54747;\n$red-alt: #F2AAAA;\n$sidebar: #444444;\n$sidebar-hover: #363636;\n$header: #222222;\n$green: #033339;\n$green-dk: #00262C;\n$body-text: lighten($sidebar, 20%);\n\n$blue: #4A90E2;\n\n$lime: #81be00;\n$grey-text: #ababab;\n$grey-bg: #FBFBFB;\n$grey-bg-dk: #F0F0F0;\n$grey-border: $grey-bg-dk;\n\n$yellow: #e9ac00;\n\n$white: #fff;\n$black: #000;\n$grey: lighten($black, 20%); // 333333\n\n//\n// Special\n//\n$link: $red;\n$link-hover: $black;\n$alert: #cccc00;\n$success: #00cc66;\n$failure: #cc0000;\n$facebook: #3B5999;\n$twitter: #00ACEE;\n\n//\n// Type\n//\n$sans: \"source_sans\", \"Lucida Grande\", \"Lucida Sans\", sans-serif;\n// $sans-light: \"source_sans_proextralight\", \"Lucida Grande\", \"Lucida Sans\",sans-serif;\n$sans-heavy: \"source_sans\", \"Lucida Grande\", \"Lucida Sans\", sans-serif;\n$serif: Georgia, serif;\n$mono: Consolas, Monaco, monospace;\n\n//\n// Base\n//\n$base-font-size: 18px;\n$base-line-height: 1.5;\n$base-font-family: $sans;\n$base-color: $sidebar;\n\n//\n// Headings\n//\n$hn-font-weight: 400;\n$hn-line-height: 1;\n$hn-font-family: $sans;\n\n$hn-color: $base-color;\n$h1-size: 36px;\n$h2-size: 30px;\n$h3-size: 18px;\n$h4-size: 16px;\n$h5-size: 16px;\n$h6-size: 16px;\n\n\n//\n// Fixed width\n//\n$mono-size: 14px;\n$mono-line-height: $base-line-height;\n$mono-font-family: $mono;\n\n\n//\n// Special\n//\n$lede-size: 24px;\n$small-size: 14px;\n\n\n//\n// Spacing\n//\n$base-spacing: $base-font-size * $base-line-height;\n$half-spacing: ceil($base-spacing / 2);\n$gutter: 20px;\n$icon-gutter: 55px;\n\n//\n// Radii\n//\n$base-radius: 3px;\n$half-radius: ceil($base-radius / 2);\n\n//\n// Grids\n//\n$page-width: 740px;\n\n$lap-start: 600px;\n$desk-start: 750px;\n$wide-start: 1000px;\n\n$ns: \"bs\";\n\n//\n// Sidebar widths\n//\n$sidebar-width: 240px;\n$nav-button-height: 52px;\n\n","@import \"../vars\";\n\n//\n// `@include media-query(min, 640px);`\n//\n@mixin media-query($type, $breakpoint: $lap-start) {\n @if $type == \"min\" {\n @media only screen and (min-width: $breakpoint) { @content }\n }\n @else if $type == \"max\" {\n @media only screen and (max-width: $breakpoint - 1px) { @content }\n }\n @else if $type == \"palm\" {\n @media only screen and (max-width: $lap-start - 1px) { @content }\n }\n @else if $type == \"lap\" {\n @media only screen and (min-width: $lap-start) and (max-width: $desk-start - 1px) { @content }\n }\n @else if $type == \"desk\" {\n @media only screen and (min-width: $desk-start) { @content }\n }\n @else if $type == \"wide\" {\n @media only screen and (min-width: $wide-start) { @content }\n }\n @else if $type == \"retina\" {\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) { @content }\n }\n}\n\n//\n// `@include font-size(10px);`\n//\n@mixin font-size($font-size){\n font-size: $font-size;\n font-size: ($font-size / $base-font-size)*1rem;\n}\n\n@mixin only-palm {\n @include media-query(min, $lap-start) {\n display: none;\n }\n}\n\n@mixin not-palm {\n\n display: none;\n @include media-query(min, $lap-start) {\n display: block;\n }\n}\n\n@mixin sidebar-style {\n background: $sidebar;\n}\n\n@mixin svg-shadow ($blur: 2px) {\n //-webkit-filter: drop-shadow( 1px 1px $blur $green-dk );\n //filter: drop-shadow( 1px 1px $blur $green-dk );\n}\n\n@mixin subtle-button ($_color, $disabled) {\n background: $white;\n color: $_color;\n border-color: darken($grey-border, 5%);\n\n &:hover, &:focus {\n color: $_color;\n background: $grey-border;\n }\n\n &:focus {\n background: $white;\n }\n\n &:active {\n color: $_color;\n text-shadow: 1px 1px 1px rgba(black, .2);\n background: darken($white, 3%);\n }\n\n &[disabled] {\n border-color: darken($grey-border, 5%);\n background: $grey-border;\n color: $disabled;\n }\n}\n","[bs-grid] {\n\n display: flex;\n width: 100%;\n flex-flow: wrap;\n\n > * {\n width: 100%;\n padding-top: $half-spacing;\n padding-bottom: $half-spacing/2;\n }\n}\n\n@include media-query(min, $desk-start) {\n [bs-grid~=\"desk-2\"] {\n [bs-grid-item] {\n flex: 0 0 50%;\n }\n }\n}\n\n[bs-grid~=\"wide-4\"] {\n [bs-grid-item] {\n @include media-query(min, $wide-start) {\n flex: 0 0 25%;\n }\n }\n}\n\n[bs-grid-item~=\"padded-right\"] {\n @include media-query(min, $lap-start) {\n padding-right: $base-spacing*2;\n }\n}\n","[ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {\n display: none !important;\n}","@import \"../vars\";\n@import \"../modules/mixins\";\n\n$header-height: 60px;\n$border-height: 4px;\n$inner-height: $header-height - $border-height;\n\n[bs-header] {\n\n position: relative;\n background: $header;\n\n @include media-query(min, $lap-start) {\n display: flex;\n }\n\n [bs-header-row~=\"brand\"] {\n\n height: $header-height;\n }\n\n [bs-header-row] {\n\n position: relative;\n width: 100%;\n display: flex;\n\n * {\n margin-top: auto;\n margin-bottom: auto;\n }\n }\n\n [bs-list~=\"header\"] {\n\n width: 100%;\n padding-left: $icon-gutter + $gutter;\n @include font-size(14px);\n\n &, a {\n color: $white;\n &:hover {\n text-decoration: none;\n }\n }\n\n a {\n display: block;\n position: relative;\n &:hover {\n color: $lime;\n text-shadow: 1px 1px 3px black;\n }\n }\n }\n}\n\n[bs-toggle] {\n\n @include font-size(24px);\n @include only-palm;\n\n position: absolute;\n right: 0;\n cursor: pointer;\n width: 55px;\n text-align: center;\n height: $header-height;\n line-height: $header-height;\n color: $white;\n transition: background .2s;\n text-shadow: 1px 1px 2px $green-dk;\n border-left: 1px solid $header;\n border-bottom: 1px solid $header;\n\n svg {\n position: absolute;\n top: $half-spacing;\n left: $half-spacing - 2px;\n height: 30px;\n width: 30px;\n pointer-events: none;\n\n &[bs-state=alt] {\n opacity: 0;\n }\n }\n\n &:hover {\n background: $sidebar;\n }\n\n &.active {\n svg {\n opacity: 0;\n &[bs-state=alt] {\n opacity: 1!important;\n }\n }\n }\n}\n\n[bs-link~=\"version\"] {\n color: $body-text;\n margin-left: $half-spacing/2;\n @include font-size(20px);\n position: relative;\n top: 4px;\n\n &:hover, &:focus {\n color: $red;\n }\n}","@import \"../vars\";\n@import \"../modules/mixins\";\n\n[bs-sidebar] {\n position: relative;\n\n @include sidebar-style;\n @include media-query(min, $lap-start) {\n width: $sidebar-width;\n\n &:after {\n content: \" \";\n width: 10px;\n height: 100%;\n position: absolute;\n right: 0;\n top: 0;\n z-index: 10;\n background: linear-gradient(to right, rgba(0, 0, 0, 0) 0%,rgba(black, .20) 100%);\n }\n }\n}\n","@import \"../vars\";\n@import \"../modules/mixins\";\n\n[bs-section-nav] {\n\n @include sidebar-style;\n\n position: absolute;\n width: 100%;\n transform: translateX(-200%) translateY(20px) scale(1.2);\n transition-timing-function: cubic-bezier(.3, 0, 0, 1.3);\n transition: all .3s;\n opacity: 0;\n z-index: 5;\n\n ul {\n margin-bottom: 0;\n }\n\n [bs-button] {\n\n text-transform: none;\n color: $grey-text;\n width: 100%;\n border-radius: 0;\n text-align: left;\n border: 0;\n position: relative;\n background: transparent;\n display: block;\n height: auto;\n padding: 11px 0 11px $icon-gutter;\n border-bottom: 1px solid $sidebar-hover;\n @include font-size(16px);\n margin-bottom: 0;\n box-shadow: 0 0 0 0;\n\n [bs-svg-icon] {\n top: 14px;\n width: 20px;\n height: 20px;\n @include svg-shadow(1px);\n }\n\n &.active {\n background: $sidebar-hover;\n z-index: 5;\n color: $white;\n\n [bs-svg-icon] {\n color: $red;\n }\n }\n\n &:hover {\n color: $white;\n background: $sidebar-hover;\n }\n &:active {\n color: $white;\n box-shadow: 0px 1px 2px 0 rgba(black, .1) inset;\n background: darken($sidebar-hover, 5%);\n }\n }\n\n @include media-query(min, $lap-start) {\n &.ready {\n opacity: 1;\n }\n position: relative;\n transform: translateX(0) translateY(0) scale(1);\n }\n\n &.active {\n transform: translateX(0) translateY(0) scale(1);\n opacity: 1;\n }\n}\n","@import \"../vars\";\n@import \"../modules/mixins\";\n\n[bs-container] {\n @include media-query(min, $lap-start) {\n display: flex;\n }\n}\n\n[bs-content] {\n\n overflow-x: hidden;\n height: auto;\n position: relative;\n background: $white;\n width: 100%;\n\n @include media-query(min, $lap-start) {\n height: 100vh;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n padding-bottom: 59px; // offset header from scroll\n margin-top: 1px;\n width: auto;\n flex: 1;\n }\n}\n\n","svg {\n\n width: 100%;\n height: 100%;\n opacity: 1;\n fill: currentColor!important;\n transition: .3s;\n\n &.icon-hidden {\n opacity: 0;\n\n }\n}\n\n",".icon {\n display: inline-block;\n}\n\n.icon-trash {\n width: 100%;\n max-width: 26px;\n height: 26px;\n}\n\n.icon-word {\n\n width: 100%;\n max-width: 150px;\n height: 100%;\n margin-left: $gutter - 5px;\n color: $white;\n\n svg {\n position: relative;\n top: -1px;\n }\n}\n\n.icon-logo {\n\n color: $white;\n transition: all .1s;\n width: $icon-gutter;\n height: 37px;\n text-align: center;\n\n &:hover {\n color: $white;\n transform: scale(1.1);\n }\n}\n\n[bs-svg-icon] {\n display: inline-block;\n width: $base-spacing;\n height: $base-spacing;\n line-height: inherit;\n position: relative;\n top: $half-spacing/2;\n use {\n width: $base-spacing;\n height: $base-spacing;\n }\n}","@import \"../vars\";\n@import \"../modules/mixins\";\n\n//\n// Site Theme\n//\nh1, h2, h3, h4, h5, h6, hgroup,\np, blockquote, address,\nul, ol, dl,\ntable,\nfieldset, figure, figcaption, details,\npre {\n margin-bottom: $half-spacing;\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3,\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n color: $hn-color;\n font-weight: $hn-font-weight;\n line-height: $hn-line-height;\n font-family: $hn-font-family;\n margin-bottom: $base-spacing;\n -webkit-font-smoothing: antialiased;\n\n small {\n font-size: inherit;\n font-weight: normal;\n }\n}\n\nh1, .h1 {\n @include font-size($h1-size);\n}\nh2, .h2 {\n padding-top: $half-spacing;\n @include font-size($h2-size);\n}\nh3, .h3 {\n @include font-size($h3-size);\n //margin-bottom: $half-spacing;\n font-weight: bold;\n}\nh4, .h4 {\n @include font-size($h4-size);\n}\nh5, .h5 {\n @include font-size($h5-size);\n}\nh6, .h6 {\n @include font-size($h6-size);\n}\n\n//\n// Custom Heading styles\n//\n[bs-heading] {\n\n @include sidebar-style;\n @include font-size(24px);\n\n padding-left: $icon-gutter;\n position: relative;\n line-height: $nav-button-height;\n margin-top: 0;\n margin-bottom: 0;\n color: $grey-bg;\n background: darken($sidebar, 2%);\n border-top: 1px solid darken($sidebar, 2%);\n\n @include media-query(min, $lap-start) {\n\n @include font-size(38px);\n color: $sidebar;\n background: $grey-bg;\n padding-left: $icon-gutter + $gutter + 5px;\n border-top: 0;\n &:before {\n display: none;\n }\n }\n\n [bs-svg-icon] {\n\n position: absolute;\n left: 14px;\n top: $half-spacing - 3px;\n\n @include media-query(min, $lap-start) {\n height: 38px;\n width: 38px;\n top: $half-spacing/2 - 1px;\n }\n }\n}\n",".lede {\n // margin-bottom: $base-spacing;\n @include font-size($lede-size);\n}\n\n.small {\n @include font-size($small-size);\n}\n","a {\n color: $link;\n transition: background 0.3s ease, color 0.3s ease;\n\n &:hover,\n &:active,\n &:focus{\n// text-decoration:underline;\n color: $link-hover;\n }\n\n [class^=\"icon-\"],\n [class*=\" icon-\"] {\n text-decoration: none;\n }\n}\n\n[bs-icon] {\n transition: background 0.3s ease, color 0.3s ease;\n}\n",".flush--bottom {\n margin-bottom: 0!important;\n}\n\n.text--cap {\n text-transform: capitalize;\n}\n\n.color--lime {\n color: $lime;\n}\n\n.hidden {\n display: none;\n &.active {\n display: block;\n }\n}\n\n%item-stack {\n margin-bottom: $half-spacing;\n}\n\n[bs-stack] {\n margin-bottom: $half-spacing;\n}\n\n\nspan.sep {\n margin-left: 5px;\n margin-right: 5px;\n}\n\n@include media-query(min, $lap-start) {\n .width-100 { width: 100%!important; }\n .width-90 { width: 90%!important; }\n .width-80 { width: 80%!important; }\n .width-70 { width: 70%!important; }\n .width-60 { width: 60%!important; }\n .width-50 { width: 50%!important; }\n .width-40 { width: 40%!important; }\n .width-30 { width: 30%!important; }\n .width-20 { width: 20%!important; }\n}\n\n@include media-query(min, $lap-start) {\n [bs-width~=\"100\"] { width: 100%!important; }\n [bs-width~=\"90\"] { width: 90%!important; }\n [bs-width~=\"80\"] { width: 80%!important; }\n [bs-width~=\"70\"] { width: 70%!important; }\n [bs-width~=\"60\"] { width: 60%!important; }\n [bs-width~=\"50\"] { width: 50%!important; }\n [bs-width~=\"40\"] { width: 40%!important; }\n [bs-width~=\"30\"] { width: 30%!important; }\n [bs-width~=\"25\"] { width: 25%!important; }\n [bs-width~=\"20\"] { width: 20%!important; }\n\n [bs-width~=\"10\"] {\n flex: 0 0 10%!important;\n }\n [bs-width~=\"5\"] {\n flex: 0 0 5%!important;\n }\n}\n\n[bs-text~=\"lede\"] {\n @include font-size(18px);\n}\n\n[bs-text~=\"mono\"] {\n font-weight: normal;\n @include font-size(16px);\n font-family: monospace;\n color: $black;\n}\n\n[bs-text~=\"micro\"] {\n @include font-size(12px);\n text-transform: uppercase;\n color: darken($grey-border, 10%);\n width: 60px;\n display: inline-block;\n text-align: right;\n margin-right: 5px;\n}\n\n[bs-color~=\"white\"] {\n color: $white;\n}\n\n[bs-color~=\"success\"] {\n color: $lime;\n}\n\n[bs-visible] {\n\n}\n\n[bs-visible~=\"not-desk\"] {\n @include media-query(min, $desk-start) {\n display: none;\n }\n}\n\n[bs-visible~=\"not-palm\"] {\n display: none!important;\n @include media-query(min, $lap-start) {\n display: inherit!important;\n }\n}\n\n[bs-visible~=\"palm\"] {\n @include media-query(min, $lap-start) {\n display: none;\n }\n}\n\n[bs-sep] {\n color: darken($grey-border, 10%);\n margin-left: 3px;\n margin-right: 3px;\n}","@import \"../vars\";\n@import \"../modules/mixins\";\n\n//\n// Default button styles\n// \n//\n[bs-button] {\n\n @include font-size(16px);\n\n display: inline-block;\n border: 1px solid darken($red, 15%);\n padding: 7px $half-spacing*1.5;\n width: auto;\n vertical-align: middle;\n background: $red;\n color: $white;\n border-radius: $base-radius;\n text-align: center;\n cursor: pointer;\n outline: none;\n transition: color .2s, background .2s;\n text-transform: uppercase;\n letter-spacing: 1px;\n //box-shadow: 0 1px 1px 0 rgba(black, .2);\n margin-bottom: $half-spacing;\n height: 40px;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n\n &:hover {\n text-decoration: none;\n color: $white;\n background: darken($red, 10%);\n }\n\n &:focus {\n text-decoration: none;\n color: $white;\n }\n\n &:active {\n color: $white;\n box-shadow: 0px 1px 0px 0 rgba(black, .1) inset;\n text-shadow: 1px 1px 0px rgba(black, .4);\n }\n\n &.success {\n\n [bs-state~=\"success\"] {\n opacity: 1;\n }\n\n [bs-state~=\"default\"] {\n opacity: 0;\n }\n\n color: $lime!important;\n }\n\n &[disabled] {\n border-color: desaturate($red, 30%);\n background: desaturate($red, 30%);\n color: #F2AAAA;\n }\n\n + .button,\n + a {\n }\n\n [bs-svg-icon] {\n position: absolute;\n top: 11px;\n left: $half-spacing;\n width: 16px;\n height: 16px;\n }\n}\n\n//\n//\n//\n[bs-button~=\"subtle\"] {\n @include subtle-button($red, $red-alt);\n}\n\n//\n//\n//\n[bs-button~=\"subtle-alt\"] {\n @include subtle-button(darken($grey-border, 40%), darken($grey-border, 20%));\n}\n\n//\n//\n//\n[bs-button~=\"size-small\"] {\n\n @include font-size(14px);\n padding: 5px $half-spacing;\n padding-top: 7px;\n height: 34px;\n\n [bs-svg-icon] {\n top: 9px;\n width: 14px;\n height: 14px;\n }\n}\n\n\n//\n// Icon\n//\n[bs-button~=\"icon\"] {\n\n padding-left: $half-spacing;\n padding-right: $half-spacing;\n\n [bs-svg-icon] {\n position: relative;\n top: 2px;\n left: auto;\n }\n}\n\n//\n// Buttons with icons on left\n//\n[bs-button~=\"icon-left\"] {\n\n position: relative;\n padding-left: $base-spacing + $half-spacing;\n\n [bs-svg-icon] {\n left: $half-spacing;\n }\n}\n\n//\n// Buttons with icons on left\n//\n[bs-button~=\"icon-right\"] {\n\n position: relative;\n padding-right: $base-spacing + $half-spacing;\n\n [bs-svg-icon] {\n left: auto;\n right: $half-spacing;\n }\n}\n\n//\n//\n//\n[bs-button-group] {\n\n display: flex;\n align-items: stretch;\n margin-bottom: $half-spacing;\n\n [bs-button] {\n border-radius: 0;\n margin-bottom: 0;\n &:first-child {\n border-top-left-radius: 3px;\n border-bottom-left-radius: 3px;\n }\n &:last-child {\n border-top-right-radius: 3px;\n border-bottom-right-radius: 3px;\n }\n }\n}\n\n[bs-button~=\"inline\"] {\n\n position: relative;\n background: transparent;\n color: $black;\n border-radius: 0;\n border: 0;\n text-transform: uppercase;\n box-shadow: 0 0 0 0;\n @include font-size(14px);\n margin-bottom: 0;\n padding-top: 10px;\n\n [bs-checkbox] {\n margin-right: 8px;\n }\n\n &:focus {\n background: transparent;\n color: $black;\n }\n\n &:hover {\n background: $grey-border;\n color: $black;\n }\n\n &:active {\n background: darken($grey-border, 10%);\n box-shadow: 0 0 0 0;\n }\n}\n\n[bs-button~=\"success\"] {\n [bs-svg-icon] {\n color: $lime;\n }\n}\n\n[bs-button-row] {\n\n background: $grey-bg;\n border-bottom: 1px solid darken($grey-border, 10%);;\n\n @include media-query(min, $lap-start) {\n padding-left: $base-spacing;\n }\n}\n\n//\n// Menu toggle\n//\n[bs-action~=\"menu-toggle\"] {\n @include only-palm;\n}\n\n//\n// Menu Close\n//\n[bs-action~=\"menu-close\"] {\n @include only-palm;\n}\n\n@mixin inline-button {\n background: $grey-bg;\n color: $grey-text;\n text-shadow: 1px 1px 0 $white;\n height: 100%;\n padding: 0;\n padding-left: $half-spacing;\n padding-right: $half-spacing;\n border-radius: 0;\n line-height: $controls-height;\n text-transform: uppercase;\n @include font-size(14px);\n\n border-left: 1px solid $grey-border;\n border-top: 1px solid $grey-border;\n border-bottom: 0;\n\n @include media-query(min, $lap-start) {\n }\n\n &:hover {\n background: lighten($grey-bg, 2%);\n box-shadow: 0 0 1px rgba(black, .1) inset;\n }\n\n &:active {\n box-shadow: 0 0 3px rgba(black, .2) inset;\n }\n}\n","$input-height: 40px;\n\n@mixin base-input {\n\n outline: none;\n vertical-align: middle;\n border-radius: $base-radius;\n outline: 0;\n height: $input-height;\n padding-left: $half-spacing/2;\n padding-right: $half-spacing;\n max-width: 100%;\n font-family: $sans;\n color: $black;\n}\n\n/*\n * Basic Inputs\n */\nbutton,\ninput,\nselect {\n @include base-input;\n}\n\n[bs-code-input] {\n width: 100%;\n border: 0;\n border: 1px dashed $grey-border;\n font-family: monospace;\n padding: $half-spacing;\n\n &:focus {\n color: $blue;\n }\n}\n\n[bs-heading-bar] {\n display: flex;\n margin-bottom: $half-spacing/2;\n [bs-input-label] {\n line-height: 36px;\n }\n [bs-button-group] {\n flex: 1;\n justify-content: flex-end;\n margin-bottom: auto;\n margin-top: auto;\n\n [bs-button] {\n padding: 3px 5px;\n height: 24px;\n font-size: 10px;\n\n @include media-query(min, $lap-start) {\n padding: 7px $half-spacing;\n height: 34px;\n font-size: 14px;\n }\n }\n }\n}\n\n[bs-textarea-input] {\n position: relative;\n margin-bottom: $half-spacing;\n [bs-tag] {\n left: -64px;\n color: #D08989;\n }\n}\n[bs-error~=\"offset\"] {\n position: absolute;\n top: 0;\n left: 0;\n}\n\n[bs-input-label] {\n\n @include font-size(14px);\n\n position: relative;\n display: block;\n text-transform: uppercase;\n font-weight: bold;\n color: $grey-text;\n letter-spacing: .5px;\n\n @include media-query(min, $lap-start) {\n @include font-size(14px);\n }\n}\n\n[bs-label-heading] {\n color: $black;\n font-weight: bold;\n}\n\n[bs-input] {\n\n padding: 0;\n border-radius: $base-radius;\n height: 100%;\n\n > * {\n margin-top: auto;\n margin-bottom: auto;\n }\n\n input {\n\n border: 0;\n border-radius: 0;\n padding: 0;\n outline: 0;\n @include font-size(16px);\n border-bottom: 1px dashed $grey-border;\n\n &:focus {\n color: $blue;\n }\n }\n\n input[type=text] {\n width: 100%;\n }\n input[type=radio] {\n &:checked {\n + label {\n color: $blue!important;\n }\n }\n }\n}\n\n[bs-input~=\"text\"] {\n height: auto;\n input {\n font-family: monospace;\n }\n}\n\n[bs-input~=\"checkbox\"] {\n\n}\n\n[bs-input~=\"inline\"] {\n\n display: flex;\n height: auto;\n\n input {\n &:focus {\n + label {\n text-decoration: underline;\n }\n }\n }\n\n > * {\n\n margin-top: auto;\n margin-bottom: auto;\n\n &:first-child {\n margin-right: $half-spacing;\n }\n }\n}\n","$spinner-color: $grey;\n.loader,\n.loader:before,\n.loader:after {\n background: $spinner-color;\n -webkit-animation: load1 .5s infinite ease-in-out;\n animation: load1 .5s infinite ease-in-out;\n width: 1em;\n height: 2em;\n}\n.loader:before,\n.loader:after {\n position: absolute;\n top: 0;\n content: '';\n}\n\n.loader:before {\n left: -1.5em;\n}\n\n.loader {\n opacity: 1;\n transition: all 1s;\n text-indent: -9999em;\n margin: 8em auto;\n position: absolute;\n font-size: 11px;\n -webkit-animation-delay: -0.16s;\n animation-delay: -0.16s;\n z-index: 1;\n left: 50%;\n &.behind {\n z-index: 0;\n }\n &.ready {\n opacity: 0;\n transform: translateY(-200%);\n }\n}\n.loader:after {\n left: 1.5em;\n -webkit-animation-delay: -0.32s;\n animation-delay: -0.32s;\n}\n\n@keyframes load1 {\n 0%,\n 80%,\n 100% {\n box-shadow: 0 0 $spinner-color;\n height: 4em;\n }\n 40% {\n box-shadow: 0 -2em $spinner-color;\n height: 5em;\n }\n}","@import \"../vars\";\n@import \"../modules/mixins\";\n\n@mixin panel {\n\n position: relative;\n\n [bs-text~=\"lede\"] {\n @include font-size(20px);\n @include media-query(min, $lap-start) {\n @include font-size(24px);\n }\n position: relative;\n margin-bottom: 0;\n color: $black;\n }\n\n [bs-text~=\"prefixed\"] {\n text-transform: none;\n span {\n text-transform: uppercase;\n color: $grey-border;\n font-weight: 200;\n }\n }\n}\n\n[bs-panel] {\n\n @include panel;\n\n background: $white;\n padding: $base-spacing 0 $half-spacing;\n border-bottom: 1px solid $grey-border;\n}\n\n[bs-panel~=\"switch\"] {\n\n &.disabled {\n background: $grey-bg;\n &, [bs-text~=\"lede\"] {\n color: $grey-text;\n }\n }\n\n [bs-panel-content] {\n\n padding-left: $base-spacing*3;\n\n @include media-query(min, $lap-start) {\n [bs-panel-icon] {\n top: $base-spacing + 6px;\n }\n padding-left: $base-spacing*4;\n }\n\n margin-bottom: $half-spacing;\n }\n\n [bs-panel-content~=\"basic\"] {\n padding-left: $half-spacing;\n padding-right: $half-spacing;\n max-width: none;\n }\n\n [bs-panel-content~=\"tight\"] {\n padding-left: 0;\n padding-right: 0;\n max-width: none;\n }\n}\n\n[bs-panel~=\"last\"] {\n\n border-bottom: 2px solid $grey-border;\n position: relative;\n\n &:after {\n content: \" \";\n width: 100%;\n height: 1px;\n display: block;\n background: $grey-border;\n position: absolute;\n bottom: -4px;\n z-index: 2;\n }\n}\n\n[bs-panel~=\"controls\"] {\n padding: 0;\n background: $grey-bg;\n border-bottom: 1px solid $grey-border;\n\n @include media-query(min, $lap-start) {\n padding: $base-spacing;\n padding-bottom: $half-spacing;\n }\n\n [bs-heading] {\n @include media-query(min, $lap-start) {\n margin-bottom: $half-spacing;\n }\n }\n}\n\n[bs-panel~=\"no-border\"] {\n border-bottom: 0;\n}\n[bs-panel~=\"outline\"] {\n border-bottom: 1px solid $grey-border;\n}\n\n[bs-panel-icon] {\n\n position: absolute;\n left: $half-spacing;\n top: $base-spacing + 3px;\n\n [bs-svg-icon] {\n color: $sidebar;\n height: 24px;\n width: 24px;\n top: 0;\n }\n}\n\n[bs-panel-content] {\n\n padding-left: $base-spacing*2;\n padding-right: $half-spacing;\n\n @include media-query(min, $lap-start) {\n\n padding-left: $base-spacing*4;\n\n [bs-panel-icon] {\n left: 44px;\n top: $base-spacing;\n [bs-svg-icon] {\n height: 30px;\n width: 30px;\n use {\n height: 30px;\n width: 30px;\n }\n }\n }\n }\n\n [bs-panel~=\"trans\"] & {\n padding-left: $base-spacing*2 + $half-spacing;\n }\n}\n\n[bs-panel-content~=\"basic\"] {\n\n padding-left: $base-spacing;\n padding-right: $base-spacing;\n max-width: 50em;\n\n @include media-query(min, $lap-start) {\n padding-left: $base-spacing*1.5;\n padding-right: $base-spacing*1.5;\n }\n}\n\n[bs-skinny] {\n @include media-query(min, $wide-start) {\n padding: $base-spacing*2 ($base-spacing*3 + $half-spacing);\n }\n}\n","$controls-height: 41px;\n\n[bs-flush] {\n margin-bottom: 0;\n border-bottom: 0;\n\n}\n\n//\n// Generic lists\n//\n[bs-list] {\n\n margin-left: 0;\n list-style: none;\n word-wrap: break-word;\n\n p {\n margin-bottom: 0;\n }\n\n [bs-button-group] {\n\n justify-content: flex-end;\n margin-bottom: 0;\n\n [bs-button] {\n height: auto;\n border: 0;\n box-shadow: 0 0 0 0;\n border-radius: 0;\n &:active {\n box-shadow: 0px 0px 1px rgba(black, .3) inset;\n }\n &:last-child {\n }\n }\n }\n}\n\n[bs-list~=\"inline\"] {\n li {\n display: inline-block;\n }\n}\n\n//\n// Bordered lists\n//\n[bs-list~=\"bordered\"] {\n\n > li {\n\n padding: ($half-spacing - 3px) $half-spacing;\n border-bottom: 1px solid $grey-border;\n\n &:first-child {\n border-top: 1px solid $grey-border;\n }\n }\n}\n\n//\n// In-list controls\n//\n[bs-list~=\"inline-controls\"] {\n\n word-wrap: break-word;\n\n p {\n margin-bottom: $half-spacing/2;\n }\n\n li {\n\n background: $white;\n position: relative;\n padding-left: $half-spacing;\n transition: background .5s;\n\n &:hover {\n\n background: $grey-bg;\n\n [bs-button~=\"subtle-alt\"] {\n color: $black;\n }\n\n [bs-button] {\n background: transparent;\n &:hover {\n color: $red;\n }\n }\n }\n\n // On wide screens, allow inline-buttons to sit on same line.\n @include media-query(min, $desk-start) {\n\n padding: 0;\n padding-left: $half-spacing;\n display: flex;\n\n p {\n margin-bottom: 0;\n flex: 1;\n padding-top: 11px;\n padding-bottom: 11px;\n }\n }\n }\n\n [bs-button-group] {\n\n margin-bottom: 0;\n\n [bs-button~=\"icon-left\"] {\n\n line-height: 35px;\n\n [bs-svg-icon] {\n top: 12px;\n }\n }\n\n [bs-svg-icon] {\n top: 4px;\n width: 22px;\n height: 22px;\n }\n }\n}\n\n[bs-tag] {\n position: absolute;\n right: calc(100% + 10px);\n text-transform: uppercase;\n font-size: 10px;\n background: #f1f1f1;\n border-radius: 3px;\n padding: 1px 3px;\n top: 6px;\n text-align: center;\n\n span {\n color: darken(#f1f1f1, 20%);\n display: block;\n }\n}\n\n[bs-tag~=\"offset\"] {\n top: 44px;\n @include media-query(min, $lap-start) {\n top: 6px;\n right: auto;\n left: -86px;\n }\n}\n\n//\n// Padded-left variant of the bs-list\n//\n[bs-list~=\"padded-left\"] {\n li {\n padding-left: $half-spacing;\n }\n}\n\n//\n// Basic version of a list\n//\n[bs-list~=\"basic\"] {\n list-style: circle;\n margin-left: $base-spacing;\n}\n\n//\n// Offset thing\n//\n[bs-offset~=\"basic\"] {\n\n > li {\n\n padding-left: $base-spacing;\n\n @include media-query(min, $lap-start) {\n padding-left: $base-spacing*1.5;\n }\n }\n}","@import \"../vars\";\n@import \"../modules/mixins\";\n\n[bs-controls] {\n width: auto;\n flex: 1;\n}\n\n[bs-controls~=\"top\"] {\n// width: 100%;\n// position: fixed;\n// bottom: 0;\n// z-index: 200;\n// @include media-query(min, $lap-start) {\n// }\n}\n\n[bs-flex~=\"top\"] {\n\n display: flex;\n background: lighten($header, 4%);\n border-bottom: 1px solid lighten($grey, 6%);\n\n @include media-query(min, $lap-start) {\n justify-content: flex-end;\n height: $header-height - 1px;\n }\n}\n\n[bs-control] {\n\n @include font-size(12px);\n\n flex: 1;\n\n @include media-query(min, $lap-start) {\n flex: none;\n height: 100%;\n padding-top: $half-spacing/2 + 3px;\n padding-left: $half-spacing;\n padding-right: $half-spacing;\n }\n\n padding-left: $half-spacing/2;\n padding-right: $half-spacing/2;\n border-left: 1px solid $grey;\n border-top: 1px solid $grey;\n position: relative;\n color: $grey-text;\n text-transform: uppercase;\n text-align: center;\n padding-top: 10px;\n padding-bottom: 6px;\n\n &:first-child {\n border-left-width: 0;\n @include media-query(min, $lap-start) {\n border-left-width: 1px;\n }\n }\n\n [bs-svg-icon] {\n transition: all .3s;\n width: 14px;\n height: 14px;\n top: 0;\n display: block;\n margin-left: auto;\n margin-right: auto;\n margin-bottom: 5px;\n\n @include media-query(min, $lap-start) {\n width: 19px;\n height: 19px;\n }\n }\n\n// &:before {\n// width: 1px;\n// height: 100%;\n// top: 0;\n// position: absolute;\n// left: -2px;\n// content: \" \";\n// background: lighten($grey, 10%);\n// }\n\n &:focus {\n text-decoration: none;\n color: $grey-text;\n }\n\n &:hover {\n\n background: $sidebar;\n text-decoration: none;\n color: $white;\n\n [bs-svg-icon] {\n transform: rotate(360deg) scale(1.1);\n color: $white;\n }\n }\n}","[bs-state~=\"success\"] {\n opacity: 0;\n color: $lime;\n}\n\n[bs-state~=\"waiting\"] {\n opacity: 0;\n color: $blue;\n}\n\n[bs-state-icons] {\n\n position: relative;\n\n [bs-svg-icon] {\n position: absolute;\n }\n}\n\n[bs-anim~=\"spin\"] {\n animation: spin 1s infinite linear;\n}\n\n[bs-state-wrapper] {\n\n display: flex;\n\n [bs-state~=\"inline\"] {\n top: 3px;\n left: $half-spacing;\n width: 17px;\n height: 27px;\n }\n\n &.waiting {\n [bs-state~=\"waiting\"] {\n opacity: 1;\n }\n }\n &.success {\n [bs-state~=\"success\"] {\n opacity: 1;\n }\n }\n}","$switch-size: 22px;\n\n.cmn-toggle {\n position: absolute;\n margin-left: -9999px;\n visibility: hidden;\n}\n.cmn-toggle + label {\n display: block;\n position: relative;\n cursor: pointer;\n outline: none;\n user-select: none;\n background: #AAAAAA;\n}\ninput.cmn-toggle-round + label {\n padding: 4px;\n width: $switch-size*2;\n height: $switch-size;\n border-radius: $base-radius;\n}\ninput.cmn-toggle-round + label:before, input.cmn-toggle-round + label:after {\n display: block;\n position: absolute;\n top: 1px;\n left: 2px;\n bottom: 1px;\n content: \"\";\n}\ninput.cmn-toggle-round + label:before {\n right: 2px;\n background-color: #AAAAAA;\n border-radius: $base-radius;\n transition: background 0.2s;\n}\ninput.cmn-toggle-round + label:after {\n top: 3px;\n width: $switch-size - 6px;\n height: $switch-size - 6px;\n background-color: $white;\n border-radius: $base-radius;\n transition: margin 0.2s;\n}\ninput.cmn-toggle-round:checked + label:before {\n background-color: $lime;\n}\n\ninput.cmn-toggle-round + label:after {\n margin-left: 1px;\n}\n\ninput.cmn-toggle-round:checked + label:after {\n margin-left: $switch-size + 1px;\n}\n\ninput.cmn-toggle-round:checked + label {\n background-color: $lime;\n\n}","$footer-text: $black;\n\n[bs-footer] {\n\n color: $footer-text;\n text-align: center;\n margin-bottom: $base-spacing;\n padding-top: $base-spacing;\n\n @include font-size(14px);\n\n @include media-query(min, $lap-start) {\n// text-shadow: 1px 1px 1px rgba(black, .4);\n padding-top: $base-spacing;\n position: fixed;\n bottom: 0;\n width: $sidebar-width;\n color: $grey-text;\n }\n\n p {\n margin-bottom: 0;\n }\n\n a {\n color: $footer-text;\n @include media-query(min, $lap-start) {\n color: $grey-text;\n }\n\n &:hover, &:focus {\n text-decoration: none;\n color: lighten($grey-text, 10%);\n }\n }\n\n [bs-icon] {\n padding: 0 10px;\n }\n\n [bs-svg-icon] {\n @include media-query(min, $lap-start) {\n @include svg-shadow;\n }\n width: 20px;\n height: 20px;\n }\n}\n\n","@import \"../vars\";\n@import \"../modules/mixins\";\n\npre {\n margin-top: $half-spacing;\n padding: $half-spacing;\n border-radius: $base-radius;\n box-shadow: -10px 0px 10px $grey-border inset;\n border: 1px solid darken($grey-border, 2%);\n\n code {\n @include font-size(12px);\n @include font-size(16px);\n color: currentColor;\n line-height: 1;\n background: transparent;\n border: 0;\n }\n}\n\ncode {\n background: $grey-bg;\n display: inline-block;\n padding: 0 5px;\n border: 1px solid $grey-border;\n color: darken($blue, 10%);\n @include font-size(14px);\n}","[bs-notify] {\n\n position: absolute;\n left: 0;\n width: 100%;\n background: $sidebar;\n color: $white;\n text-align: center;\n padding: $base-spacing $half-spacing;\n box-shadow: 0 5px 5px 0px rgba(0, 0, 0, .2);\n transform: translateY(-200%);\n transition: all .3s;\n z-index: 100;\n\n &.active {\n transform: translateY(0);\n }\n\n p {\n margin-bottom: 0;\n }\n\n &.success {\n\n }\n\n &.error {\n background: #ED6A13;\n }\n}","@mixin cover-all {\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n right: 0;\n}\n\n[bs-overlay] {\n\n @include cover-all;\n background: rgba(black, .9);\n padding: $base-spacing*2 $half-spacing;\n color: $white;\n text-align: center;\n visibility: hidden;\n z-index: 2000;\n\n &.active {\n visibility: visible;\n }\n\n * {\n color: $white;\n }\n\n [bs-svg-icon] {\n width: 40px;\n height: 40px;\n @include media-query(min, $lap-start) {\n width: 100px;\n height: 100px;\n }\n }\n}"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/public/favicon.ico b/web/node_modules/browser-sync-ui/public/favicon.ico deleted file mode 100644 index 0af4d9a..0000000 Binary files a/web/node_modules/browser-sync-ui/public/favicon.ico and /dev/null differ diff --git a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-bold-webfont.eot b/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-bold-webfont.eot deleted file mode 100755 index 757770c..0000000 Binary files a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-bold-webfont.eot and /dev/null differ diff --git a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-bold-webfont.svg b/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-bold-webfont.svg deleted file mode 100755 index 45748b1..0000000 --- a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-bold-webfont.svg +++ /dev/null @@ -1,954 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-bold-webfont.ttf b/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-bold-webfont.ttf deleted file mode 100755 index 024d878..0000000 Binary files a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-bold-webfont.ttf and /dev/null differ diff --git a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-bold-webfont.woff b/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-bold-webfont.woff deleted file mode 100755 index 6472cae..0000000 Binary files a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-bold-webfont.woff and /dev/null differ diff --git a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-bold-webfont.woff2 b/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-bold-webfont.woff2 deleted file mode 100755 index f40dd64..0000000 Binary files a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-bold-webfont.woff2 and /dev/null differ diff --git a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-it-webfont.eot b/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-it-webfont.eot deleted file mode 100755 index 572021a..0000000 Binary files a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-it-webfont.eot and /dev/null differ diff --git a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-it-webfont.svg b/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-it-webfont.svg deleted file mode 100755 index 9d0a4b0..0000000 --- a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-it-webfont.svg +++ /dev/null @@ -1,842 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-it-webfont.ttf b/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-it-webfont.ttf deleted file mode 100755 index a02ed65..0000000 Binary files a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-it-webfont.ttf and /dev/null differ diff --git a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-it-webfont.woff b/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-it-webfont.woff deleted file mode 100755 index 8bc506a..0000000 Binary files a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-it-webfont.woff and /dev/null differ diff --git a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-it-webfont.woff2 b/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-it-webfont.woff2 deleted file mode 100755 index 8a0b169..0000000 Binary files a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-it-webfont.woff2 and /dev/null differ diff --git a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-regular-webfont.eot b/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-regular-webfont.eot deleted file mode 100755 index 4c09b06..0000000 Binary files a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-regular-webfont.eot and /dev/null differ diff --git a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-regular-webfont.svg b/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-regular-webfont.svg deleted file mode 100755 index 1fb716c..0000000 --- a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-regular-webfont.svg +++ /dev/null @@ -1,977 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-regular-webfont.ttf b/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-regular-webfont.ttf deleted file mode 100755 index 3dbcf66..0000000 Binary files a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-regular-webfont.ttf and /dev/null differ diff --git a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-regular-webfont.woff b/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-regular-webfont.woff deleted file mode 100755 index 27476d1..0000000 Binary files a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-regular-webfont.woff and /dev/null differ diff --git a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-regular-webfont.woff2 b/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-regular-webfont.woff2 deleted file mode 100755 index 6732059..0000000 Binary files a/web/node_modules/browser-sync-ui/public/fonts/source-sans/sourcesanspro-regular-webfont.woff2 and /dev/null differ diff --git a/web/node_modules/browser-sync-ui/public/img/favicon.ico b/web/node_modules/browser-sync-ui/public/img/favicon.ico deleted file mode 100644 index 83f19a3..0000000 Binary files a/web/node_modules/browser-sync-ui/public/img/favicon.ico and /dev/null differ diff --git a/web/node_modules/browser-sync-ui/public/img/icons/icons.svg b/web/node_modules/browser-sync-ui/public/img/icons/icons.svg deleted file mode 100644 index edea5bb..0000000 --- a/web/node_modules/browser-sync-ui/public/img/icons/icons.svg +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Rectangle 1 + Rectangle 2 + Rectangle 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - browser - - - - - - - - - - - - - - - - - - - - - - - Fill 213 + Fill 132 - - - - - - - Twitter - - - - - - - \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/public/img/icons/preview.html b/web/node_modules/browser-sync-ui/public/img/icons/preview.html deleted file mode 100644 index b8fcab7..0000000 --- a/web/node_modules/browser-sync-ui/public/img/icons/preview.html +++ /dev/null @@ -1,429 +0,0 @@ - - - - - Document - - - - -
-

Symbols

-

Example usage:

-
<svg><use xlink:href="icons.svg#svg-logo"></use></svg>
-
-
-
-
- -
-
-
svg-bin
-
-
-
- -
-
-
svg-block
-
-
-
- -
-
-
svg-book
-
-
-
- -
-
-
svg-bug
-
-
-
- -
-
-
svg-circle-delete
-
-
-
- -
-
-
svg-circle-minus
-
-
-
- -
-
-
svg-circle-ok
-
-
-
- -
-
-
svg-circle-pause
-
-
-
- -
-
-
svg-circle-play
-
-
-
- -
-
-
svg-circle-plus
-
-
-
- -
-
-
svg-code
-
-
-
- -
-
-
svg-cog
-
-
-
- -
-
-
svg-devices
-
-
-
- -
-
-
svg-github
-
-
-
- -
-
-
svg-globe
-
-
-
- -
-
-
svg-help
-
-
-
- -
-
-
svg-home
-
-
-
- -
-
-
svg-imac
-
-
-
- -
-
-
svg-jh
-
-
-
- -
-
-
svg-list
-
-
-
- -
-
-
svg-list2
-
-
-
- -
-
-
svg-logo-word
-
-
-
- -
-
-
svg-logo
-
-
-
- -
-
-
svg-newtab
-
-
-
- -
-
-
svg-pen
-
-
-
- -
-
-
svg-pencil
-
-
-
- -
-
-
svg-plug
-
-
-
- -
-
-
svg-repeat
-
-
-
- -
-
-
svg-square-add
-
-
-
- -
-
-
svg-square-up
-
-
-
- -
-
-
svg-sync-browser
-
-
-
- -
-
-
svg-sync
-
-
-
- -
-
-
svg-syncall
-
-
-
- -
-
-
svg-target
-
-
-
- -
-
-
svg-terminal
-
-
-
- -
-
-
svg-time
-
-
-
- -
-
-
svg-trash
-
-
-
- -
-
-
svg-twitter
-
-
-
- -
-
-
svg-wifi
-
-
-
- - diff --git a/web/node_modules/browser-sync-ui/public/img/logo.svg b/web/node_modules/browser-sync-ui/public/img/logo.svg deleted file mode 100644 index 94b3b1e..0000000 --- a/web/node_modules/browser-sync-ui/public/img/logo.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/web/node_modules/browser-sync-ui/public/img/ps-bg.gif b/web/node_modules/browser-sync-ui/public/img/ps-bg.gif deleted file mode 100644 index 6f2b61c..0000000 Binary files a/web/node_modules/browser-sync-ui/public/img/ps-bg.gif and /dev/null differ diff --git a/web/node_modules/browser-sync-ui/public/index.html b/web/node_modules/browser-sync-ui/public/index.html deleted file mode 100644 index afed259..0000000 --- a/web/node_modules/browser-sync-ui/public/index.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - Browsersync - - - - - - - - - - %svg% - - - - -
- - %header% - -
- -
-
Loading...
- -
- %footer% -
-
- -
- - %pageMarkup% - %templates% - -
- -
- %footer% -
- -
-
-
- - - - - - - - - - diff --git a/web/node_modules/browser-sync-ui/public/js/app.js b/web/node_modules/browser-sync-ui/public/js/app.js deleted file mode 100644 index 6db3290..0000000 --- a/web/node_modules/browser-sync-ui/public/js/app.js +++ /dev/null @@ -1,25 +0,0 @@ -!function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){function r(e){e.html5Mode({enabled:!0,requireBase:!1})}n(2),n(4),n(6),n(8);var i=window.angular;i.module("BrowserSync",["bsHistory","bsClients","bsDisconnect","bsNotify","bsSocket","bsStore","ngRoute","ngTouch","ngSanitize"]).config(["$locationProvider",r]);n(10),n(11),n(12),n(13),n(14),n(15),n(17),n(18),n(22),n(23),n(25)},function(e,t,n){n(3),e.exports=angular},function(e,t){/** - * @license AngularJS v1.4.14 - * (c) 2010-2015 Google, Inc. http://angularjs.org - * License: MIT - */ -!function(e,t,n){"use strict";function r(e,t){return t=t||Error,function(){var n,r,i=2,o=arguments,a=o[0],s="["+(e?e+":":"")+a+"] ",u=o[1];for(s+=u.replace(/\{\d+\}/g,function(e){var t=+e.slice(1,-1),n=t+i;return n=0&&(t-1 in e||e instanceof Array)||"function"==typeof e.item)}function o(e,t,n){var r,a;if(e)if(k(e))for(r in e)"prototype"==r||"length"==r||"name"==r||e.hasOwnProperty&&!e.hasOwnProperty(r)||t.call(n,e[r],r,e);else if(Lr(e)||i(e)){var s="object"!=typeof e;for(r=0,a=e.length;r=0&&e.splice(n,1),n}function U(e,t){function n(e,t){var n,i=t.$$hashKey;if(Lr(e))for(var o=0,a=e.length;o2?L(arguments,2):[];return!k(t)||t instanceof RegExp?t:n.length?function(){return arguments.length?t.apply(e,B(n,arguments,0)):t.apply(e,n)}:function(){return arguments.length?t.apply(e,arguments):t.call(e)}}function W(e,r){var i=r;return"string"==typeof e&&"$"===e.charAt(0)&&"$"===e.charAt(1)?i=n:O(r)?i="$WINDOW":r&&t===r?i="$DOCUMENT":M(r)&&(i="$SCOPE"),i}function G(e,t){return y(e)?n:(E(t)||(t=t?2:null),JSON.stringify(e,W,t))}function Y(e){return S(e)?JSON.parse(e):e}function J(e,t){e=e.replace(Xr,"");var n=Date.parse("Jan 01, 1970 00:00:00 "+e)/6e4;return isNaN(n)?t:n}function X(e,t){return e=new Date(e.getTime()),e.setMinutes(e.getMinutes()+t),e}function Z(e,t,n){n=n?-1:1;var r=e.getTimezoneOffset(),i=J(t,r);return X(e,n*(i-r))}function K(e){e=jr(e).clone();try{e.empty()}catch(e){}var t=jr("
").append(e).html();try{return e[0].nodeType===ni?kr(t):t.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(e,t){return"<"+kr(t)})}catch(e){return kr(t)}}function Q(e){try{return decodeURIComponent(e)}catch(e){}}function ee(e){var t={};return o((e||"").split("&"),function(e){var n,r,i;e&&(r=e=e.replace(/\+/g,"%20"),n=e.indexOf("="),n!==-1&&(r=e.substring(0,n),i=e.substring(n+1)),r=Q(r),b(r)&&(i=!b(i)||Q(i),Ar.call(t,r)?Lr(t[r])?t[r].push(i):t[r]=[t[r],i]:t[r]=i))}),t}function te(e){var t=[];return o(e,function(e,n){Lr(e)?o(e,function(e){t.push(re(n,!0)+(e===!0?"":"="+re(e,!0)))}):t.push(re(n,!0)+(e===!0?"":"="+re(e,!0)))}),t.length?t.join("&"):""}function ne(e){return re(e,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function re(e,t){return encodeURIComponent(e).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,t?"%20":"+")}function ie(e,t){var n,r,i=Zr.length;for(r=0;r/,">"))}r=r||[],r.unshift(["$provide",function(e){e.value("$rootElement",n)}]),i.debugInfoEnabled&&r.push(["$compileProvider",function(e){e.debugInfoEnabled(!0)}]),r.unshift("ng");var o=tt(r,i.strictDi);return o.invoke(["$rootScope","$rootElement","$compile","$injector",function(e,t,n,r){e.$apply(function(){t.data("$injector",r),n(t)(e)})}]),o},u=/^NG_ENABLE_DEBUG_INFO!/,c=/^NG_DEFER_BOOTSTRAP!/;return e&&u.test(e.name)&&(i.debugInfoEnabled=!0,e.name=e.name.replace(u,"")),e&&!c.test(e.name)?s():(e.name=e.name.replace(c,""),Fr.resumeBootstrap=function(e){return o(e,function(e){r.push(e)}),s()},void(k(Fr.resumeDeferredBootstrap)&&Fr.resumeDeferredBootstrap()))}function se(){e.name="NG_ENABLE_DEBUG_INFO!"+e.name,e.location.reload()}function ue(e){var t=Fr.element(e).injector();if(!t)throw Ur("test","no injector found for element argument to getTestability");return t.get("$$testability")}function ce(e,t){return t=t||"_",e.replace(Kr,function(e,n){return(n?t:"")+e.toLowerCase()})}function le(){var t;if(!Qr){var r=Jr();Vr=y(r)?e.jQuery:r?e[r]:n,Vr&&Vr.fn.on?(jr=Vr,f(Vr.fn,{scope:wi.scope,isolateScope:wi.isolateScope,controller:wi.controller,injector:wi.injector,inheritedData:wi.inheritedData}),t=Vr.cleanData,Vr.cleanData=function(e){var n;if(Br)Br=!1;else for(var r,i=0;null!=(r=e[i]);i++)n=Vr._data(r,"events"),n&&n.$destroy&&Vr(r).triggerHandler("$destroy");t(e)}):jr=Me,Fr.element=jr,Qr=!0}}function fe(e,t,n){if(!e)throw Ur("areq","Argument '{0}' is {1}",t||"?",n||"required");return e}function he(e,t,n){return n&&Lr(e)&&(e=e[e.length-1]),fe(k(e),t,"not a function, got "+(e&&"object"==typeof e?e.constructor.name||"Object":typeof e)),e}function pe(e,t){if("hasOwnProperty"===e)throw Ur("badname","hasOwnProperty is not a valid {0} name",t)}function de(e,t,n){if(!t)return e;for(var r,i=t.split("."),o=e,a=i.length,s=0;s=0)return"...";t.push(n)}return n})}function ye(e){return"function"==typeof e?e.toString().replace(/ \{[\s\S]*$/,""):y(e)?"undefined":"string"!=typeof e?ge(e):e}function be(t){f(t,{bootstrap:ae,copy:U,extend:f,merge:h,equals:H,element:jr,forEach:o,injector:tt,noop:$,bind:z,toJson:G,fromJson:Y,identity:v,isUndefined:y,isDefined:b,isString:S,isFunction:k,isObject:w,isNumber:E,isElement:_,isArray:Lr,version:ai,isDate:C,lowercase:kr,uppercase:Or,callbacks:{counter:0},getTestability:ue,$$minErr:r,$$csp:Yr,reloadWithDebugInfo:se}),(Dr=me(e))("ng",["ngLocale"],["$provide",function(e){e.provider({$$sanitizeUri:bn}),e.provider("$compile",ft).directive({a:ko,input:zo,textarea:zo,form:No,script:Ia,select:Ua,style:Ha,option:Fa,ngBind:Yo,ngBindHtml:Xo,ngBindTemplate:Jo,ngClass:Ko,ngClassEven:ea,ngClassOdd:Qo,ngCloak:ta,ngController:na,ngForm:jo,ngHide:Na,ngIf:oa,ngInclude:aa,ngInit:ua,ngNonBindable:xa,ngPluralize:ka,ngRepeat:Aa,ngShow:Ta,ngStyle:ja,ngSwitch:Va,ngSwitchWhen:Da,ngSwitchDefault:Pa,ngOptions:Ca,ngTransclude:_a,ngModel:ya,ngList:ca,ngChange:Zo,pattern:La,ngPattern:La,required:Ba,ngRequired:Ba,minlength:Wa,ngMinlength:Wa,maxlength:za,ngMaxlength:za,ngValue:Go,ngModelOptions:wa}).directive({ngInclude:sa}).directive(Ao).directive(ra),e.provider({$anchorScroll:nt,$animate:_i,$animateCss:qi,$$animateJs:Di,$$animateQueue:Pi,$$AnimateRunner:Ri,$$animateAsyncRun:Ii,$browser:ut,$cacheFactory:ct,$controller:vt,$document:mt,$exceptionHandler:gt,$filter:Dn,$$forceReflow:Li,$interpolate:jt,$interval:Vt,$http:Ot,$httpParamSerializer:bt,$httpParamSerializerJQLike:wt,$httpBackend:Tt,$xhrFactory:Mt,$location:Gt,$log:Yt,$parse:dn,$rootScope:yn,$q:$n,$$q:vn,$sce:En,$sceDelegate:Sn,$sniffer:Cn,$templateCache:lt,$templateRequest:kn,$$testability:An,$timeout:On,$window:Nn,$$rAF:gn,$$jqLite:Xe,$$HashMap:Ci,$$cookieReader:Vn})}])}function we(){return++ui}function xe(e){return e.replace(fi,function(e,t,n,r){return r?n.toUpperCase():n}).replace(hi,"Moz$1")}function Se(e){return!vi.test(e)}function Ee(e){var t=e.nodeType;return t===ei||!t||t===ii}function Ce(e){for(var t in si[e.ng339])return!0;return!1}function ke(e,t){var n,r,i,a,s=t.createDocumentFragment(),u=[];if(Se(e))u.push(t.createTextNode(e));else{for(n=n||s.appendChild(t.createElement("div")),r=(mi.exec(e)||["",""])[1].toLowerCase(),i=yi[r]||yi._default,n.innerHTML=i[1]+e.replace(gi,"<$1>")+i[2],a=i[0];a--;)n=n.lastChild;u=B(u,n.childNodes),n=s.firstChild,n.textContent=""}return s.textContent="",s.innerHTML="",o(u,function(e){s.appendChild(e)}),s}function Ae(e,n){n=n||t;var r;return(r=$i.exec(e))?[n.createElement(r[1])]:(r=ke(e,n))?r.childNodes:[]}function Oe(e,t){var n=e.parentNode;n&&n.replaceChild(t,e),t.appendChild(e)}function Me(e){if(e instanceof Me)return e;var t;if(S(e)&&(e=Wr(e),t=!0),!(this instanceof Me)){if(t&&"<"!=e.charAt(0))throw di("nosel","Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element");return new Me(e)}t?qe(this,Ae(e)):qe(this,e)}function Te(e){return e.cloneNode(!0)}function Ne(e,t){if(t||Ve(e),e.querySelectorAll)for(var n=e.querySelectorAll("*"),r=0,i=n.length;r0||(li(e,t,s),delete a[t])};o(t.split(" "),function(e){u(e),pi[e]&&u(pi[e])})}else for(t in a)"$destroy"!==t&&li(e,t,s),delete a[t]}function Ve(e,t){var r=e.ng339,i=r&&si[r];if(i){if(t)return void delete i.data[t];i.handle&&(i.events.$destroy&&i.handle({},"$destroy"),je(e)),delete si[r],e.ng339=n}}function De(e,t){var r=e.ng339,i=r&&si[r];return t&&!i&&(e.ng339=r=we(),i=si[r]={events:{},data:{},handle:n}),i}function Pe(e,t,n){if(Ee(e)){var r=b(n),i=!r&&t&&!w(t),o=!t,a=De(e,!i),s=a&&a.data;if(r)s[t]=n;else{if(o)return s;if(i)return s&&s[t];f(s,t)}}}function _e(e,t){return!!e.getAttribute&&(" "+(e.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").indexOf(" "+t+" ")>-1}function Ie(e,t){t&&e.setAttribute&&o(t.split(" "),function(t){e.setAttribute("class",Wr((" "+(e.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+Wr(t)+" "," ")))})}function Re(e,t){if(t&&e.setAttribute){var n=(" "+(e.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ");o(t.split(" "),function(e){e=Wr(e),n.indexOf(" "+e+" ")===-1&&(n+=e+" ")}),e.setAttribute("class",Wr(n))}}function qe(e,t){if(t)if(t.nodeType)e[e.length++]=t;else{var n=t.length;if("number"==typeof n&&t.window!==t){if(n)for(var r=0;r1&&(i=F(i));for(var u=0;uc&&this.remove(p.key),t}},get:function(e){if(c").append(e).html())):n?wi.clone.call(e):e,a)for(var c in a)u.data("$"+c+"Controller",a[c].instance);return D.$$addScopeInfo(u,t),n&&n(u,t),l&&l(t,u,u,i),u}}function P(e){var t=e&&e[0];return t&&"foreignobject"!==R(t)&&t.toString().match(/SVG/)?"svg":"html"}function _(e,t,r,i,o,a){function s(e,r,i,o){var a,s,u,c,l,f,h,p,v;if(d){var m=r.length;for(v=new Array(m),l=0;l<$.length;l+=3)h=$[l],v[h]=r[h]}else v=r;for(l=0,f=$.length;l0)}else r.push(e);return jr(r)}function B(e,t,n){return function(r,i,o,a,s){return i=F(i[0],t,n),e(r,i,o,a,s)}}function z(e,r,o,a,s,u,c,l,f){function h(e,t,n,r){e&&(n&&(e=B(e,n,r)),e.require=v.require,e.directiveName=g,(T===v||v.$$isolateScope)&&(e=oe(e,{isolateScope:!0})),c.push(e)),t&&(n&&(t=B(t,n,r)),t.require=v.require,t.directiveName=g,(T===v||v.$$isolateScope)&&(t=oe(t,{isolateScope:!0})),l.push(t))}function p(e,t,n,r){var i;if(S(t)){var o=t.match(x),a=t.substring(o[0].length),s=o[1]||o[3],u="?"===o[2];if("^^"===s?n=n.parent():(i=r&&r[a],i=i&&i.instance),!i){var c="$"+a+"Controller";i=s?n.inheritedData(c):n.data(c)}if(!i&&!u)throw Ui("ctreq","Controller '{0}', required by directive '{1}', can't be found!",a,e)}else if(Lr(t)){i=[];for(var l=0,f=t.length;l=0;H--)f=l[H],ae(f,f.isolateScope?h:t,g,y,f.require&&p(f.directiveName,f.require,g,v),m)}f=f||{};for(var v,g,y,b,E,C=-Number.MAX_VALUE,A=f.newScopeDirective,O=f.controllerDirectives,T=f.newIsolateScopeDirective,N=f.templateDirective,j=f.nonTlbTranscludeDirective,V=!1,P=!1,_=f.hasElementTranscludeDirective,I=o.$$element=jr(r),R=u,q=a,H=0,z=e.length;Hv.priority)break;if((E=v.scope)&&(v.templateUrl||(w(E)?(Q("new/isolated scope",T||A,v,I),T=v):Q("new/isolated scope",T,v,I)),A=A||v),g=v.name,!v.templateUrl&&v.controller&&(E=v.controller,O=O||ve(),Q("'"+g+"' controller",O[g],v,I),O[g]=v),(E=v.transclude)&&(V=!0,v.$$tlb||(Q("transclusion",j,v,I),j=v),"element"==E?(_=!0,C=v.priority,y=I,I=o.$$element=jr(t.createComment(" "+g+": "+o[g]+" ")),r=I[0],ie(s,L(y),r),q=D(y,a,C,R&&R.name,{nonTlbTranscludeDirective:j})):(y=jr(Te(r)).contents(),I.empty(),q=D(y,a,n,n,{needsNewScope:v.$$isolateScope||v.$$newScope}))),v.template)if(P=!0,Q("template",N,v,I),N=v,E=k(v.template)?v.template(I,o):v.template,E=pe(E),v.replace){if(R=v,y=Se(E)?[]:dt(te(v.templateNamespace,Wr(E))),r=y[0],1!=y.length||r.nodeType!==ei)throw Ui("tplrt","Template for directive '{0}' must have exactly one root element. {1}",g,"");ie(s,I,r);var Z={$attr:{}},ee=U(r,[],Z),ne=e.splice(H+1,e.length-(H+1));(T||A)&&W(ee,T,A),e=e.concat(ee).concat(ne),J(o,Z),z=e.length}else I.html(E);if(v.templateUrl)P=!0,Q("template",N,v,I),N=v,v.replace&&(R=v),$=X(e.splice(H,e.length-H),I,o,s,V&&q,c,l,{controllerDirectives:O,newScopeDirective:A!==v&&A,newIsolateScopeDirective:T,templateDirective:N,nonTlbTranscludeDirective:j}),z=e.length;else if(v.compile)try{b=v.compile(I,o,q),k(b)?h(null,b,G,Y):b&&h(b.pre,b.post,G,Y)}catch(e){i(e,K(I))}v.terminal&&($.terminal=!0,C=Math.max(C,v.priority))}return $.scope=A&&A.scope===!0,$.transcludeOnThisElement=V,$.templateOnThisElement=P,$.transclude=q,f.hasElementTranscludeDirective=_,$}function W(e,t,n){for(var r=0,i=e.length;rp.priority)&&p.restrict.indexOf(r)!=-1){if(u&&(p=d(p,{$$start:u,$$end:f})),!p.$$bindings){var g=p.$$bindings=a(p,p.name);w(g.isolateScope)&&(p.$$isolateBindings=g.isolateScope)}t.push(p),h=p}}catch(e){i(e)}return h}function Y(t){if(c.hasOwnProperty(t))for(var n,r=e.get(t+l),i=0,o=r.length;i"+n+"",r.childNodes[0].childNodes;default:return n}}function ne(e,t){if("srcdoc"==t)return O.HTML;var n=R(e);return"xlinkHref"==t||"form"==n&&"action"==t||"img"!=n&&("src"==t||"ngSrc"==t)?O.RESOURCE_URL:void 0}function re(e,t,n,i,o){var a=ne(e,i);o=g[i]||o;var s=r(n,!0,a,o);if(s){if("multiple"===i&&"select"===R(e))throw Ui("selmulti","Binding to the 'multiple' attribute is not supported. Element: {0}",K(e));t.push({priority:100,compile:function(){return{pre:function(e,t,u){var c=u.$$observers||(u.$$observers=ve());if(E.test(i))throw Ui("nodomevents","Interpolations for HTML DOM event attributes are disallowed. Please use the ng- versions (such as ng-click instead of onclick) instead.");var l=u[i];l!==n&&(s=l&&r(l,!0,a,o),n=l),s&&(u[i]=s(e),(c[i]||(c[i]=[])).$$inter=!0,(u.$$observers&&u.$$observers[i].$$scope||e).$watch(s,function(e,t){"class"===i&&e!=t?u.$updateClass(e,t):u.$set(i,e)}))}}}})}}function ie(e,n,r){var i,o,a=n[0],s=n.length,u=a.parentNode;if(e)for(i=0,o=e.length;i0&&T.addClass(this.$$element,e)},$removeClass:function(e){e&&e.length>0&&T.removeClass(this.$$element,e)},$updateClass:function(e,t){var n=pt(e,t);n&&n.length&&T.addClass(this.$$element,n);var r=pt(t,e);r&&r.length&&T.removeClass(this.$$element,r)},$set:function(e,t,n,r){var a,s=this.$$element[0],u=ze(s,e),c=We(e),l=e;if(u?(this.$$element.prop(e,t),r=u):c&&(this[c]=t,l=c),this[e]=t,r?this.$attr[e]=r:(r=this.$attr[e],r||(this.$attr[e]=r=ce(e,"-"))),a=R(this.$$element),"a"===a&&"href"===e||"img"===a&&"src"===e)this[e]=t=N(t,"src"===e);else if("img"===a&&"srcset"===e&&b(t)){for(var f="",h=Wr(t),p=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,d=/\s/.test(h)?p:/(,)/,$=h.split(d),v=Math.floor($.length/2),m=0;m0?" ":"")+a}return n}function dt(e){e=jr(e);var t=e.length;if(t<=1)return e;for(;t--;){var n=e[t];n.nodeType===ri&&_r.call(e,t,1)}return e}function $t(e,t){if(t&&S(t))return t;if(S(e)){var n=Bi.exec(e);if(n)return n[3]}}function vt(){var e={},t=!1;this.register=function(t,n){pe(t,"controller"),w(t)?f(e,t):e[t]=n},this.allowGlobals=function(){t=!0},this.$get=["$injector","$window",function(i,o){function a(e,t,n,i){if(!e||!w(e.$scope))throw r("$controller")("noscp","Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",i,t);e.$scope[t]=n}return function(r,s,u,c){var l,h,p,d;if(u=u===!0,c&&S(c)&&(d=c),S(r)){if(h=r.match(Bi),!h)throw Hi("ctrlfmt","Badly formed controller string '{0}'. Must match `__name__ as __id__` or `__name__`.",r);p=h[1],d=d||h[3],r=e.hasOwnProperty(p)?e[p]:de(s.$scope,p,!0)||(t?de(o,p,!0):n),he(r,p,!0)}if(u){var $=(Lr(r)?r[r.length-1]:r).prototype;l=Object.create($||null),d&&a(s,d,l,p||r.name);var v;return v=f(function(){var e=i.invoke(r,l,s,p);return e!==l&&(w(e)||k(e))&&(l=e,d&&a(s,d,l,p||r.name)),l},{instance:l,identifier:d})}return l=i.instantiate(r,s,p),d&&a(s,d,l,p||r.name),l}}]}function mt(){this.$get=["$window",function(e){return jr(e.document)}]}function gt(){this.$get=["$log",function(e){return function(t,n){e.error.apply(e,arguments)}}]}function yt(e){return w(e)?C(e)?e.toISOString():G(e):e}function bt(){this.$get=function(){return function(e){if(!e)return"";var t=[];return a(e,function(e,n){null===e||y(e)||(Lr(e)?o(e,function(e,r){t.push(re(n)+"="+re(yt(e)))}):t.push(re(n)+"="+re(yt(e))))}),t.join("&")}}}function wt(){this.$get=function(){return function(e){function t(e,r,i){null===e||y(e)||(Lr(e)?o(e,function(e,n){t(e,r+"["+(w(e)?n:"")+"]")}):w(e)&&!C(e)?a(e,function(e,n){t(e,r+(i?"":"[")+n+(i?"":"]"))}):n.push(re(r)+"="+re(yt(e))))}if(!e)return"";var n=[];return t(e,"",!0),n.join("&")}}}function xt(e,t){if(S(e)){var n=e.replace(Ji,"").trim();if(n){var r=t("Content-Type");(r&&0===r.indexOf(zi)||St(n))&&(e=Y(n))}}return e}function St(e){var t=e.match(Gi);return t&&Yi[t[0]].test(e)}function Et(e){function t(e,t){e&&(r[e]=r[e]?r[e]+", "+t:t)}var n,r=ve();return S(e)?o(e.split("\n"),function(e){n=e.indexOf(":"),t(kr(Wr(e.substr(0,n))),Wr(e.substr(n+1)))}):w(e)&&o(e,function(e,n){t(kr(n),Wr(e))}),r}function Ct(e){var t;return function(n){if(t||(t=Et(e)),n){var r=t[kr(n)];return void 0===r&&(r=null),r}return t}}function kt(e,t,n,r){return k(r)?r(e,t,n):(o(r,function(r){e=r(e,t,n)}),e)}function At(e){return 200<=e&&e<300}function Ot(){var e=this.defaults={transformResponse:[xt],transformRequest:[function(e){return!w(e)||T(e)||j(e)||N(e)?e:G(e)}],headers:{common:{Accept:"application/json, text/plain, */*"},post:F(Wi),put:F(Wi),patch:F(Wi)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer"},t=!1;this.useApplyAsync=function(e){return b(e)?(t=!!e,this):t};var i=!0;this.useLegacyPromiseExtensions=function(e){return b(e)?(i=!!e,this):i};var a=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector",function(s,u,c,l,h,p){function d(t){function a(e){var t=f({},e);return t.data=kt(e.data,e.headers,e.status,c.transformResponse),At(e.status)?t:h.reject(t)}function s(e,t){var n,r={};return o(e,function(e,i){k(e)?(n=e(t),null!=n&&(r[i]=n)):r[i]=e}),r}function u(t){var n,r,i,o=e.headers,a=f({},t.headers);o=f({},o.common,o[kr(t.method)]);e:for(n in o){r=kr(n);for(i in a)if(kr(i)===r)continue e;a[n]=o[n]}return s(a,F(t))}if(!Fr.isObject(t))throw r("$http")("badreq","Http request configuration must be an object. Received: {0}",t);if(!S(t.url))throw r("$http")("badreq","Http request configuration url must be a string. Received: {0}",t.url);var c=f({method:"get",transformRequest:e.transformRequest,transformResponse:e.transformResponse,paramSerializer:e.paramSerializer},t);c.headers=u(t),c.method=Or(c.method),c.paramSerializer=S(c.paramSerializer)?p.get(c.paramSerializer):c.paramSerializer;var l=function(t){var r=t.headers,i=kt(t.data,Ct(r),n,t.transformRequest);return y(i)&&o(r,function(e,t){"content-type"===kr(t)&&delete r[t]}),y(t.withCredentials)&&!y(e.withCredentials)&&(t.withCredentials=e.withCredentials),m(t,i).then(a,a)},d=[l,n],$=h.when(c);for(o(E,function(e){(e.request||e.requestError)&&d.unshift(e.request,e.requestError),(e.response||e.responseError)&&d.push(e.response,e.responseError)});d.length;){var v=d.shift(),g=d.shift();$=$.then(v,g)}return i?($.success=function(e){return he(e,"fn"),$.then(function(t){e(t.data,t.status,t.headers,c)}),$},$.error=function(e){return he(e,"fn"),$.then(null,function(t){e(t.data,t.status,t.headers,c)}),$}):($.success=Zi("success"),$.error=Zi("error")),$}function $(e){o(arguments,function(e){d[e]=function(t,n){return d(f({},n||{},{method:e,url:t}))}})}function v(e){o(arguments,function(e){d[e]=function(t,n,r){return d(f({},r||{},{method:e,url:t,data:n}))}})}function m(r,i){function o(e,n,r,i){function o(){a(n,e,r,i)}p&&(At(e)?p.put(E,[e,n,Et(r),i]):p.remove(E)),t?l.$applyAsync(o):(o(),l.$$phase||l.$apply())}function a(e,t,n,i){t=t>=-1?t:0,(At(t)?v.resolve:v.reject)({data:e,status:t,headers:Ct(n),config:r,statusText:i})}function c(e){a(e.data,e.status,F(e.headers()),e.statusText)}function f(){var e=d.pendingRequests.indexOf(r);e!==-1&&d.pendingRequests.splice(e,1)}var p,$,v=h.defer(),m=v.promise,S=r.headers,E=g(r.url,r.paramSerializer(r.params));if(d.pendingRequests.push(r),m.then(f,f),!r.cache&&!e.cache||r.cache===!1||"GET"!==r.method&&"JSONP"!==r.method||(p=w(r.cache)?r.cache:w(e.cache)?e.cache:x),p&&($=p.get(E),b($)?D($)?$.then(c,c):Lr($)?a($[1],$[0],F($[2]),$[3]):a($,200,{},"OK"):p.put(E,m)),y($)){var C=Tn(r.url)?u()[r.xsrfCookieName||e.xsrfCookieName]:n;C&&(S[r.xsrfHeaderName||e.xsrfHeaderName]=C),s(r.method,E,i,o,S,r.timeout,r.withCredentials,r.responseType)}return m}function g(e,t){return t.length>0&&(e+=(e.indexOf("?")==-1?"?":"&")+t),e}var x=c("$http");e.paramSerializer=S(e.paramSerializer)?p.get(e.paramSerializer):e.paramSerializer;var E=[];return o(a,function(e){E.unshift(S(e)?p.get(e):p.invoke(e))}),d.pendingRequests=[],$("get","delete","head","jsonp"),v("post","put","patch"),d.defaults=e,d}]}function Mt(){this.$get=function(){return function(){return new e.XMLHttpRequest}}}function Tt(){this.$get=["$browser","$window","$document","$xhrFactory",function(e,t,n,r){return Nt(e,r,e.defer,t.angular.callbacks,n[0])}]}function Nt(e,t,n,r,i){function a(e,t,n){var o=i.createElement("script"),a=null;return o.type="text/javascript",o.src=e,o.async=!0,a=function(e){li(o,"load",a),li(o,"error",a),i.body.removeChild(o),o=null;var s=-1,u="unknown";e&&("load"!==e.type||r[t].called||(e={type:"error"}),u=e.type,s="error"===e.type?404:200),n&&n(s,u)},ci(o,"load",a),ci(o,"error",a),i.body.appendChild(o),a}return function(i,s,u,c,l,f,h,p){function d(){g&&g(),w&&w.abort()}function v(t,r,i,o,a){b(S)&&n.cancel(S),g=w=null,t(r,i,o,a),e.$$completeOutstandingRequest($)}if(e.$$incOutstandingRequestCount(),s=s||e.url(),"jsonp"==kr(i)){var m="_"+(r.counter++).toString(36);r[m]=function(e){r[m].data=e,r[m].called=!0};var g=a(s.replace("JSON_CALLBACK","angular.callbacks."+m),m,function(e,t){v(c,e,r[m].data,"",t),r[m]=$})}else{var w=t(i,s);w.open(i,s,!0),o(l,function(e,t){b(e)&&w.setRequestHeader(t,e)}),w.onload=function(){var e=w.statusText||"",t="response"in w?w.response:w.responseText,n=1223===w.status?204:w.status;0===n&&(n=t?200:"file"==Mn(s).protocol?404:0),v(c,n,t,w.getAllResponseHeaders(),e)};var x=function(){v(c,-1,null,null,"")};if(w.onerror=x,w.onabort=x,h&&(w.withCredentials=!0),p)try{w.responseType=p}catch(e){if("json"!==p)throw e}w.send(y(u)?null:u)}if(f>0)var S=n(d,f);else D(f)&&f.then(d)}}function jt(){var e="{{",t="}}";this.startSymbol=function(t){return t?(e=t,this):e},this.endSymbol=function(e){return e?(t=e,this):t},this.$get=["$parse","$exceptionHandler","$sce",function(n,r,i){function o(e){return"\\\\\\"+e}function a(n){return n.replace(h,e).replace(p,t)}function s(e){if(null==e)return"";switch(typeof e){case"string":break;case"number":e=""+e;break;default:e=G(e)}return e}function u(o,u,h,p){function d(e){try{return e=O(e),p&&!b(e)?e:s(e)}catch(e){r(Ki.interr(o,e))}}p=!!p;for(var $,v,m,g=0,w=[],x=[],S=o.length,E=[],C=[];g1&&Ki.throwNoconcat(o),!u||w.length){var A=function(e){for(var t=0,n=w.length;t4,l=c?L(arguments,4):[],f=t.setInterval,h=t.clearInterval,p=0,d=b(u)&&!u,$=(d?r:n).defer(),v=$.promise;return s=b(s)?s:0,v.then(null,null,c?function(){i.apply(null,l)}:i),v.$$intervalId=f(function(){$.notify(p++),s>0&&p>=s&&($.resolve(p),h(v.$$intervalId),delete o[v.$$intervalId]),d||e.$apply()},a),o[v.$$intervalId]=$,v}var o={};return i.cancel=function(e){return!!(e&&e.$$intervalId in o)&&(o[e.$$intervalId].reject("canceled"),t.clearInterval(e.$$intervalId),delete o[e.$$intervalId],!0)},i}]}function Dt(e){for(var t=e.split("/"),n=t.length;n--;)t[n]=ne(t[n]);return t.join("/")}function Pt(e,t){var n=Mn(e);t.$$protocol=n.protocol,t.$$host=n.hostname,t.$$port=p(n.port)||eo[n.protocol]||null}function _t(e,t){var n="/"!==e.charAt(0);n&&(e="/"+e);var r=Mn(e);t.$$path=decodeURIComponent(n&&"/"===r.pathname.charAt(0)?r.pathname.substring(1):r.pathname),t.$$search=ee(r.search),t.$$hash=decodeURIComponent(r.hash),t.$$path&&"/"!=t.$$path.charAt(0)&&(t.$$path="/"+t.$$path)}function It(e,t){if(0===t.indexOf(e))return t.substr(e.length)}function Rt(e){var t=e.indexOf("#");return t==-1?e:e.substr(0,t)}function qt(e){return e.replace(/(#.+)|#$/,"$1")}function Ut(e){return e.substr(0,Rt(e).lastIndexOf("/")+1)}function Ft(e){return e.substring(0,e.indexOf("/",e.indexOf("//")+2))}function Ht(e,t,n){this.$$html5=!0,n=n||"",Pt(e,this),this.$$parse=function(e){var n=It(t,e);if(!S(n))throw to("ipthprfx",'Invalid url "{0}", missing path prefix "{1}".',e,t);_t(n,this),this.$$path||(this.$$path="/"),this.$$compose()},this.$$compose=function(){var e=te(this.$$search),n=this.$$hash?"#"+ne(this.$$hash):"";this.$$url=Dt(this.$$path)+(e?"?"+e:"")+n,this.$$absUrl=t+this.$$url.substr(1)},this.$$parseLinkUrl=function(r,i){if(i&&"#"===i[0])return this.hash(i.slice(1)),!0;var o,a,s;return b(o=It(e,r))?(a=o,s=b(o=It(n,o))?t+(It("/",o)||o):e+a):b(o=It(t,r))?s=t+o:t==r+"/"&&(s=t),s&&this.$$parse(s),!!s}}function Bt(e,t,n){Pt(e,this),this.$$parse=function(r){function i(e,t,n){var r,i=/^\/[A-Z]:(\/.*)/;return 0===t.indexOf(n)&&(t=t.replace(n,"")),i.exec(t)?e:(r=i.exec(e),r?r[1]:e)}var o,a=It(e,r)||It(t,r);y(a)||"#"!==a.charAt(0)?this.$$html5?o=a:(o="",y(a)&&(e=r,this.replace())):(o=It(n,a),y(o)&&(o=a)),_t(o,this),this.$$path=i(this.$$path,o,e),this.$$compose()},this.$$compose=function(){var t=te(this.$$search),r=this.$$hash?"#"+ne(this.$$hash):"";this.$$url=Dt(this.$$path)+(t?"?"+t:"")+r,this.$$absUrl=e+(this.$$url?n+this.$$url:"")},this.$$parseLinkUrl=function(t,n){return Rt(e)==Rt(t)&&(this.$$parse(t),!0)}}function Lt(e,t,n){this.$$html5=!0,Bt.apply(this,arguments),this.$$parseLinkUrl=function(r,i){if(i&&"#"===i[0])return this.hash(i.slice(1)),!0;var o,a;return e==Rt(r)?o=r:(a=It(t,r))?o=e+n+a:t===r+"/"&&(o=t),o&&this.$$parse(o),!!o},this.$$compose=function(){var t=te(this.$$search),r=this.$$hash?"#"+ne(this.$$hash):"";this.$$url=Dt(this.$$path)+(t?"?"+t:"")+r,this.$$absUrl=e+n+this.$$url}}function zt(e){return function(){return this[e]}}function Wt(e,t){return function(n){return y(n)?this[e]:(this[e]=t(n),this.$$compose(),this)}}function Gt(){var e="",t={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(t){return b(t)?(e=t,this):e},this.html5Mode=function(e){return V(e)?(t.enabled=e,this):w(e)?(V(e.enabled)&&(t.enabled=e.enabled),V(e.requireBase)&&(t.requireBase=e.requireBase),V(e.rewriteLinks)&&(t.rewriteLinks=e.rewriteLinks),this):t},this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(n,r,i,o,a){function s(e,t,n){var i=c.url(),o=c.$$state;try{r.url(e,t,n),c.$$state=r.state()}catch(e){throw c.url(i),c.$$state=o,e}}function u(e,t){n.$broadcast("$locationChangeSuccess",c.absUrl(),e,c.$$state,t)}var c,l,f,h=r.baseHref(),p=r.url();if(t.enabled){if(!h&&t.requireBase)throw to("nobase","$location in HTML5 mode requires a tag to be present!");f=Ft(p)+(h||"/"),l=i.history?Ht:Lt}else f=Rt(p),l=Bt;var d=Ut(f);c=new l(f,d,"#"+e),c.$$parseLinkUrl(p,p),c.$$state=r.state();var $=/^\s*(javascript|mailto):/i;o.on("click",function(e){if(t.rewriteLinks&&!e.ctrlKey&&!e.metaKey&&!e.shiftKey&&2!=e.which&&2!=e.button){for(var i=jr(e.target);"a"!==R(i[0]);)if(i[0]===o[0]||!(i=i.parent())[0])return;var s=i.prop("href"),u=i.attr("href")||i.attr("xlink:href");w(s)&&"[object SVGAnimatedString]"===s.toString()&&(s=Mn(s.animVal).href),$.test(s)||!s||i.attr("target")||e.isDefaultPrevented()||c.$$parseLinkUrl(s,u)&&(e.preventDefault(),c.absUrl()!=r.url()&&(n.$apply(),a.angular["ff-684208-preventDefault"]=!0))}}),qt(c.absUrl())!=qt(p)&&r.url(c.absUrl(),!0);var v=!0;return r.onUrlChange(function(e,t){return y(It(d,e))?void(a.location.href=e):(n.$evalAsync(function(){var r,i=c.absUrl(),o=c.$$state;e=qt(e),c.$$parse(e),c.$$state=t,r=n.$broadcast("$locationChangeStart",e,i,t,o).defaultPrevented,c.absUrl()===e&&(r?(c.$$parse(i),c.$$state=o,s(i,!1,o)):(v=!1,u(i,o)))}),void(n.$$phase||n.$digest()))}),n.$watch(function(){var e=qt(r.url()),t=qt(c.absUrl()),o=r.state(),a=c.$$replace,l=e!==t||c.$$html5&&i.history&&o!==c.$$state;(v||l)&&(v=!1,n.$evalAsync(function(){var t=c.absUrl(),r=n.$broadcast("$locationChangeStart",t,e,c.$$state,o).defaultPrevented;c.absUrl()===t&&(r?(c.$$parse(e),c.$$state=o):(l&&s(t,a,o===c.$$state?null:c.$$state),u(e,o)))})),c.$$replace=!1}),c}]}function Yt(){var e=!0,t=this;this.debugEnabled=function(t){return b(t)?(e=t,this):e},this.$get=["$window",function(n){function r(e){return e instanceof Error&&(e.stack?e=e.message&&e.stack.indexOf(e.message)===-1?"Error: "+e.message+"\n"+e.stack:e.stack:e.sourceURL&&(e=e.message+"\n"+e.sourceURL+":"+e.line)),e}function i(e){var t=n.console||{},i=t[e]||t.log||$,a=!1;try{a=!!i.apply}catch(e){}return a?function(){var e=[];return o(arguments,function(t){e.push(r(t))}),i.apply(t,e)}:function(e,t){i(e,null==t?"":t)}}return{log:i("log"),info:i("info"),warn:i("warn"),error:i("error"),debug:function(){var n=i("debug");return function(){e&&n.apply(t,arguments)}}()}}]}function Jt(e,t){if("__defineGetter__"===e||"__defineSetter__"===e||"__lookupGetter__"===e||"__lookupSetter__"===e||"__proto__"===e)throw ro("isecfld","Attempting to access a disallowed field in Angular expressions! Expression: {0}",t);return e}function Xt(e,t){if(e+="",!S(e))throw ro("iseccst","Cannot convert object to primitive value! Expression: {0}",t);return e}function Zt(e,t){if(e){if(e.constructor===e)throw ro("isecfn","Referencing Function in Angular expressions is disallowed! Expression: {0}",t);if(e.window===e)throw ro("isecwindow","Referencing the Window in Angular expressions is disallowed! Expression: {0}",t);if(e.children&&(e.nodeName||e.prop&&e.attr&&e.find))throw ro("isecdom","Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}",t);if(e===Object)throw ro("isecobj","Referencing Object in Angular expressions is disallowed! Expression: {0}",t)}return e}function Kt(e,t){if(e){if(e.constructor===e)throw ro("isecfn","Referencing Function in Angular expressions is disallowed! Expression: {0}",t);if(e===io||e===oo||e===ao)throw ro("isecff","Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}",t)}}function Qt(e,t){if(e&&(e===(0).constructor||e===(!1).constructor||e==="".constructor||e==={}.constructor||e===[].constructor||e===Function.constructor))throw ro("isecaf","Assigning to a constructor is disallowed! Expression: {0}",t)}function en(e,t){return"undefined"!=typeof e?e:t}function tn(e,t){return"undefined"==typeof e?t:"undefined"==typeof t?e:e+t}function nn(e,t){var n=e(t);return!n.$stateful}function rn(e,t){var n,r;switch(e.type){case lo.Program:n=!0,o(e.body,function(e){rn(e.expression,t),n=n&&e.expression.constant}),e.constant=n;break;case lo.Literal:e.constant=!0,e.toWatch=[];break;case lo.UnaryExpression:rn(e.argument,t),e.constant=e.argument.constant,e.toWatch=e.argument.toWatch;break;case lo.BinaryExpression:rn(e.left,t),rn(e.right,t),e.constant=e.left.constant&&e.right.constant,e.toWatch=e.left.toWatch.concat(e.right.toWatch);break;case lo.LogicalExpression:rn(e.left,t),rn(e.right,t),e.constant=e.left.constant&&e.right.constant,e.toWatch=e.constant?[]:[e];break;case lo.ConditionalExpression:rn(e.test,t),rn(e.alternate,t),rn(e.consequent,t),e.constant=e.test.constant&&e.alternate.constant&&e.consequent.constant,e.toWatch=e.constant?[]:[e];break;case lo.Identifier:e.constant=!1,e.toWatch=[e];break;case lo.MemberExpression:rn(e.object,t),e.computed&&rn(e.property,t),e.constant=e.object.constant&&(!e.computed||e.property.constant),e.toWatch=[e];break;case lo.CallExpression:n=!!e.filter&&nn(t,e.callee.name),r=[],o(e.arguments,function(e){rn(e,t),n=n&&e.constant,e.constant||r.push.apply(r,e.toWatch)}),e.constant=n,e.toWatch=e.filter&&nn(t,e.callee.name)?r:[e];break;case lo.AssignmentExpression:rn(e.left,t),rn(e.right,t),e.constant=e.left.constant&&e.right.constant,e.toWatch=[e];break;case lo.ArrayExpression:n=!0,r=[],o(e.elements,function(e){rn(e,t),n=n&&e.constant,e.constant||r.push.apply(r,e.toWatch)}),e.constant=n,e.toWatch=r;break;case lo.ObjectExpression:n=!0,r=[],o(e.properties,function(e){rn(e.value,t),n=n&&e.value.constant,e.value.constant||r.push.apply(r,e.value.toWatch)}),e.constant=n,e.toWatch=r;break;case lo.ThisExpression:e.constant=!1,e.toWatch=[]}}function on(e){if(1==e.length){var t=e[0].expression,r=t.toWatch;return 1!==r.length?r:r[0]!==t?r:n}}function an(e){return e.type===lo.Identifier||e.type===lo.MemberExpression}function sn(e){if(1===e.body.length&&an(e.body[0].expression))return{type:lo.AssignmentExpression,left:e.body[0].expression,right:{type:lo.NGValueParameter},operator:"="}}function un(e){return 0===e.body.length||1===e.body.length&&(e.body[0].expression.type===lo.Literal||e.body[0].expression.type===lo.ArrayExpression||e.body[0].expression.type===lo.ObjectExpression)}function cn(e){return e.constant}function ln(e,t){this.astBuilder=e,this.$filter=t}function fn(e,t){this.astBuilder=e,this.$filter=t}function hn(e){return"constructor"==e}function pn(e){return k(e.valueOf)?e.valueOf():ho.call(e)}function dn(){var e=ve(),t=ve();this.$get=["$filter",function(r){function i(n,i,o){var s,p,g;switch(o=o||m,typeof n){case"string":n=n.trim(),g=n;var y=o?t:e;if(s=y[g],!s){":"===n.charAt(0)&&":"===n.charAt(1)&&(p=!0,n=n.substring(2));var b=o?v:d,w=new co(b),x=new fo(w,r,b);s=x.parse(n),s.constant?s.$$watchDelegate=f:p?s.$$watchDelegate=s.literal?l:c:s.inputs&&(s.$$watchDelegate=u),o&&(s=a(s)),y[g]=s}return h(s,i);case"function":return h(n,i);default:return h($,i)}}function a(e){function t(t,n,r,i){var o=m;m=!0;try{return e(t,n,r,i)}finally{m=o}}if(!e)return e;t.$$watchDelegate=e.$$watchDelegate,t.assign=a(e.assign),t.constant=e.constant,t.literal=e.literal;for(var n=0;e.inputs&&n0&&c(this.$$state),r.promise},catch:function(e){return this.then(null,e)},finally:function(e,t){return this.then(function(t){return m(t,!0,e)},function(t){return m(t,!1,e)},t)}}),f(l.prototype,{resolve:function(e){this.promise.$$state.status||(e===this.promise?this.$$reject(p("qcycle","Expected promise to be resolved with value other than itself '{0}'",e)):this.$$resolve(e)); -},$$resolve:function(e){var n,r;r=i(this,this.$$resolve,this.$$reject);try{(w(e)||k(e))&&(n=e&&e.then),k(n)?(this.promise.$$state.status=-1,n.call(e,r[0],r[1],this.notify)):(this.promise.$$state.value=e,this.promise.$$state.status=1,c(this.promise.$$state))}catch(e){r[1](e),t(e)}},reject:function(e){this.promise.$$state.status||this.$$reject(e)},$$reject:function(e){this.promise.$$state.value=e,this.promise.$$state.status=2,c(this.promise.$$state)},notify:function(n){var r=this.promise.$$state.pending;this.promise.$$state.status<=0&&r&&r.length&&e(function(){for(var e,i,o=0,a=r.length;o=0&&g(o,-1),a=null}},$watchGroup:function(e,t){function n(){u=!1,c?(c=!1,t(i,i,s)):t(i,r,s)}var r=new Array(e.length),i=new Array(e.length),a=[],s=this,u=!1,c=!0;if(!e.length){var l=!0;return s.$evalAsync(function(){l&&t(i,i,s)}),function(){l=!1}}return 1===e.length?this.$watch(e[0],function(e,n,o){i[0]=e,r[0]=n,t(i,e===n?i:r,o)}):(o(e,function(e,t){var o=s.$watch(e,function(e,o){i[t]=e,r[t]=o,u||(u=!0,s.$evalAsync(n))});a.push(o)}),function(){for(;a.length;)a.shift()()})},$watchCollection:function(e,t){function n(e){o=e;var t,n,r,s,u;if(!y(o)){if(w(o))if(i(o)){a!==p&&(a=p,v=a.length=0,f++),t=o.length,v!==t&&(f++,a.length=v=t);for(var c=0;ct){f++;for(n in a)Ar.call(o,n)||(v--,delete a[n])}}else a!==o&&(a=o,f++);return f}}function r(){if($?($=!1,t(o,o,u)):t(o,s,u),c)if(w(o))if(i(o)){s=new Array(o.length);for(var e=0;e1,f=0,h=l(e,n),p=[],d={},$=!0,v=0;return this.$watch(h,r)},$digest:function(){var e,r,i,o,u,l,h,p,d,$,g,y,b=t,w=this,E=[];v("$digest"),f.$$checkUrlChange(),this===C&&null!==s&&(f.defer.cancel(s),S()),a=null;do{for(p=!1,$=w;A.length;){try{y=A.shift(),y.scope.$eval(y.expression,y.locals)}catch(e){c(e)}a=null}e:do{if(l=$.$$watchers)for(h=l.length;h--;)try{if(e=l[h])if(u=e.get,(r=u($))===(i=e.last)||(e.eq?H(r,i):"number"==typeof r&&"number"==typeof i&&isNaN(r)&&isNaN(i))){if(e===a){p=!1;break e}}else p=!0,a=e,e.last=e.eq?U(r,null):r,o=e.fn,o(r,i===x?r:i,$),b<5&&(g=4-b,E[g]||(E[g]=[]),E[g].push({msg:k(e.exp)?"fn: "+(e.exp.name||e.exp.toString()):e.exp,newVal:r,oldVal:i}))}catch(e){c(e)}if(!(d=$.$$watchersCount&&$.$$childHead||$!==w&&$.$$nextSibling))for(;$!==w&&!(d=$.$$nextSibling);)$=$.$parent}while($=d);if((p||A.length)&&!b--)throw m(),n("infdig","{0} $digest() iterations reached. Aborting!\nWatchers fired in the last 5 iterations: {1}",t,E)}while(p||A.length);for(m();O.length;)try{O.shift()()}catch(e){c(e)}},$destroy:function(){if(!this.$$destroyed){var e=this.$parent;this.$broadcast("$destroy"),this.$$destroyed=!0,this===C&&f.$$applicationDestroyed(),g(this,-this.$$watchersCount);for(var t in this.$$listenerCount)b(this,this.$$listenerCount[t],t);e&&e.$$childHead==this&&(e.$$childHead=this.$$nextSibling),e&&e.$$childTail==this&&(e.$$childTail=this.$$prevSibling),this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling),this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling),this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=$,this.$on=this.$watch=this.$watchGroup=function(){return $},this.$$listeners={},this.$$nextSibling=null,p(this)}},$eval:function(e,t){return l(e)(this,t)},$evalAsync:function(e,t){C.$$phase||A.length||f.defer(function(){A.length&&C.$digest()}),A.push({scope:this,expression:l(e),locals:t})},$$postDigest:function(e){O.push(e)},$apply:function(e){try{v("$apply");try{return this.$eval(e)}finally{m()}}catch(e){c(e)}finally{try{C.$digest()}catch(e){throw c(e),e}}},$applyAsync:function(e){function t(){n.$eval(e)}var n=this;e&&M.push(t),e=l(e),E()},$on:function(e,t){var n=this.$$listeners[e];n||(this.$$listeners[e]=n=[]),n.push(t);var r=this;do r.$$listenerCount[e]||(r.$$listenerCount[e]=0),r.$$listenerCount[e]++;while(r=r.$parent);var i=this;return function(){var r=n.indexOf(t);r!==-1&&(n[r]=null,b(i,1,e))}},$emit:function(e,t){var n,r,i,o=[],a=this,s=!1,u={name:e,targetScope:a,stopPropagation:function(){s=!0},preventDefault:function(){u.defaultPrevented=!0},defaultPrevented:!1},l=B([u],arguments,1);do{for(n=a.$$listeners[e]||o,u.currentScope=a,r=0,i=n.length;r-1)throw po("iwcard","Illegal sequence *** in string matcher. String: {0}",e);return e=Gr(e).replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*"),new RegExp("^"+e+"$")}if(A(e))return new RegExp("^"+e.source+"$");throw po("imatcher",'Matchers may only be "self", string patterns or RegExp objects')}function xn(e){var t=[];return b(e)&&o(e,function(e){t.push(wn(e))}),t}function Sn(){this.SCE_CONTEXTS=$o;var e=["self"],t=[];this.resourceUrlWhitelist=function(t){return arguments.length&&(e=xn(t)),e},this.resourceUrlBlacklist=function(e){return arguments.length&&(t=xn(e)),t},this.$get=["$injector",function(n){function r(e,t){return"self"===e?Tn(t):!!e.exec(t.href)}function i(n){var i,o,a=Mn(n.toString()),s=!1;for(i=0,o=e.length;i to the top of your HTML document. See http://docs.angularjs.org/api/ng.$sce for more information.");var r=F($o);r.isEnabled=function(){return e},r.trustAs=n.trustAs,r.getTrusted=n.getTrusted,r.valueOf=n.valueOf,e||(r.trustAs=r.getTrusted=function(e,t){return t},r.valueOf=v),r.parseAs=function(e,n){var i=t(n);return i.literal&&i.constant?i:t(n,function(t){return r.getTrusted(e,t)})};var i=r.parseAs,a=r.getTrusted,s=r.trustAs;return o($o,function(e,t){var n=kr(t);r[xe("parse_as_"+n)]=function(t){return i(e,t)},r[xe("get_trusted_"+n)]=function(t){return a(e,t)},r[xe("trust_as_"+n)]=function(t){return s(e,t)}}),r}]}function Cn(){this.$get=["$window","$document",function(e,t){var n,r,i={},o=p((/android (\d+)/.exec(kr((e.navigator||{}).userAgent))||[])[1]),a=/Boxee/i.test((e.navigator||{}).userAgent),s=t[0]||{},u=/^(Moz|webkit|ms)(?=[A-Z])/,c=s.body&&s.body.style,l=!1,f=!1;if(c){for(var h in c)if(r=u.exec(h)){n=r[0],n=n.substr(0,1).toUpperCase()+n.substr(1);break}n||(n="WebkitOpacity"in c&&"webkit"),l=!!("transition"in c||n+"Transition"in c),f=!!("animation"in c||n+"Animation"in c),!o||l&&f||(l=S(c.webkitTransition),f=S(c.webkitAnimation))}return{history:!(!e.history||!e.history.pushState||o<4||a),hasEvent:function(e){if("input"===e&&Nr<=11)return!1;if(y(i[e])){var t=s.createElement("div");i[e]="on"+e in t}return i[e]},csp:Yr(),vendorPrefix:n,transitions:l,animations:f,android:o}}]}function kn(){this.$get=["$templateCache","$http","$q","$sce",function(e,t,n,r){function i(o,a){function s(e){if(!a)throw Ui("tpload","Failed to load template: {0} (HTTP status: {1} {2})",o,e.status,e.statusText);return n.reject(e)}i.totalPendingRequests++,S(o)&&!y(e.get(o))||(o=r.getTrustedResourceUrl(o));var u=t.defaults&&t.defaults.transformResponse;Lr(u)?u=u.filter(function(e){return e!==xt}):u===xt&&(u=null);var c={cache:e,transformResponse:u};return t.get(o,c).finally(function(){i.totalPendingRequests--}).then(function(t){return e.put(o,t.data),t.data},s)}return i.totalPendingRequests=0,i}]}function An(){this.$get=["$rootScope","$browser","$location",function(e,t,n){var r={};return r.findBindings=function(e,t,n){var r=e.getElementsByClassName("ng-binding"),i=[];return o(r,function(e){var r=Fr.element(e).data("$binding");r&&o(r,function(r){if(n){var o=new RegExp("(^|\\s)"+Gr(t)+"(\\s|\\||$)");o.test(r)&&i.push(e)}else r.indexOf(t)!=-1&&i.push(e)})}),i},r.findModels=function(e,t,n){for(var r=["ng-","data-ng-","ng\\:"],i=0;i0&&(u=t(o.substring(0,s)),y(r[u])&&(r[u]=t(o.substring(s+1))));return r}}function Vn(){this.$get=jn}function Dn(e){function t(r,i){if(w(r)){var a={};return o(r,function(e,n){a[n]=t(n,e)}),a}return e.factory(r+n,i)}var n="Filter";this.register=t,this.$get=["$injector",function(e){return function(t){return e.get(t+n)}}],t("currency",qn),t("date",er),t("filter",Pn),t("json",tr),t("limitTo",nr),t("lowercase",Eo),t("number",Un),t("orderBy",rr),t("uppercase",Co)}function Pn(){return function(e,t,n){if(!i(e)){if(null==e)return e;throw r("filter")("notarray","Expected array but received: {0}",e)}var o,a,s=Rn(t);switch(s){case"function":o=t;break;case"boolean":case"null":case"number":case"string":a=!0;case"object":o=_n(t,n,a);break;default:return e}return Array.prototype.filter.call(e,o)}}function _n(e,t,n){var r,i=w(e)&&"$"in e;return t===!0?t=H:k(t)||(t=function(e,t){return!y(e)&&(null===e||null===t?e===t:!(w(t)||w(e)&&!g(e))&&(e=kr(""+e),t=kr(""+t),e.indexOf(t)!==-1))}),r=function(r){return i&&!w(r)?In(r,e.$,t,!1):In(r,e,t,n)}}function In(e,t,n,r,i){var o=Rn(e),a=Rn(t);if("string"===a&&"!"===t.charAt(0))return!In(e,t.substring(1),n,r);if(Lr(e))return e.some(function(e){return In(e,t,n,r)});switch(o){case"object":var s;if(r){for(s in e)if("$"!==s.charAt(0)&&In(e[s],t,n,!0))return!0;return!i&&In(e,t,n,!1)}if("object"===a){for(s in t){var u=t[s];if(!k(u)&&!y(u)){var c="$"===s,l=c?e:e[s];if(!In(l,u,n,c,c))return!1}}return!0}return n(e,t);case"function":return!1;default:return n(e,t)}}function Rn(e){return null===e?"null":typeof e}function qn(e){var t=e.NUMBER_FORMATS;return function(e,n,r){return y(n)&&(n=t.CURRENCY_SYM),y(r)&&(r=t.PATTERNS[1].maxFrac),null==e?e:Bn(e,t.PATTERNS[1],t.GROUP_SEP,t.DECIMAL_SEP,r).replace(/\u00A4/g,n)}}function Un(e){var t=e.NUMBER_FORMATS;return function(e,n){return null==e?e:Bn(e,t.PATTERNS[0],t.GROUP_SEP,t.DECIMAL_SEP,n)}}function Fn(e){var t,n,r,i,o,a=0;for((n=e.indexOf(yo))>-1&&(e=e.replace(yo,"")),(r=e.search(/e/i))>0?(n<0&&(n=r),n+=+e.slice(r+1),e=e.substring(0,r)):n<0&&(n=e.length),r=0;e.charAt(r)==bo;r++);if(r==(o=e.length))t=[0],n=1;else{for(o--;e.charAt(o)==bo;)o--;for(n-=r,t=[],i=0;r<=o;r++,i++)t[i]=+e.charAt(r)}return n>go&&(t=t.splice(0,go-1),a=n-1,n=1),{d:t,e:a,i:n}}function Hn(e,t,n,r){var i=e.d,o=i.length-e.i;t=y(t)?Math.min(Math.max(n,o),r):+t;var a=t+e.i,s=i[a];if(a>0)i.splice(a);else{e.i=1,i.length=a=t+1;for(var u=0;u=5&&i[a-1]++;o0?p=l.splice(f,l.length):(p=l,l=[0]);var d=[];for(l.length>=t.lgSize&&d.unshift(l.splice(-t.lgSize,l.length).join(""));l.length>t.gSize;)d.unshift(l.splice(-t.gSize,l.length).join(""));l.length&&d.unshift(l.join("")),c=d.join(n),p.length&&(c+=r+p.join("")),h&&(c+="e+"+h)}return e<0&&!s?t.negPre+c+t.negSuf:t.posPre+c+t.posSuf}function Ln(e,t,n){var r="";for(e<0&&(r="-",e=-e),e=""+e;e.length0||o>-n)&&(o+=n),0===o&&n==-12&&(o=12),Ln(o,t,r)}}function Wn(e,t){return function(n,r){var i=n["get"+e](),o=Or(t?"SHORT"+e:e);return r[o][i]}}function Gn(e,t,n){var r=-1*n,i=r>=0?"+":"";return i+=Ln(Math[r>0?"floor":"ceil"](r/60),2)+Ln(Math.abs(r%60),2)}function Yn(e){var t=new Date(e,0,1).getDay();return new Date(e,0,(t<=4?5:12)-t)}function Jn(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+(4-e.getDay()))}function Xn(e){return function(t){var n=Yn(t.getFullYear()),r=Jn(t),i=+r-+n,o=1+Math.round(i/6048e5);return Ln(o,e)}}function Zn(e,t){return e.getHours()<12?t.AMPMS[0]:t.AMPMS[1]}function Kn(e,t){return e.getFullYear()<=0?t.ERAS[0]:t.ERAS[1]}function Qn(e,t){return e.getFullYear()<=0?t.ERANAMES[0]:t.ERANAMES[1]}function er(e){function t(e){var t;if(t=e.match(n)){var r=new Date(0),i=0,o=0,a=t[8]?r.setUTCFullYear:r.setFullYear,s=t[8]?r.setUTCHours:r.setHours;t[9]&&(i=p(t[9]+t[10]),o=p(t[9]+t[11])),a.call(r,p(t[1]),p(t[2])-1,p(t[3]));var u=p(t[4]||0)-i,c=p(t[5]||0)-o,l=p(t[6]||0),f=Math.round(1e3*parseFloat("0."+(t[7]||0)));return s.call(r,u,c,l,f),r}return e}var n=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(n,r,i){var a,s,u="",c=[];if(r=r||"mediumDate",r=e.DATETIME_FORMATS[r]||r,S(n)&&(n=So.test(n)?p(n):t(n)),E(n)&&(n=new Date(n)),!C(n)||!isFinite(n.getTime()))return n;for(;r;)s=xo.exec(r),s?(c=B(c,s,1),r=c.pop()):(c.push(r),r=null);var l=n.getTimezoneOffset();return i&&(l=J(i,l),n=Z(n,i,!0)),o(c,function(t){a=wo[t],u+=a?a(n,e.DATETIME_FORMATS,l):"''"===t?"'":t.replace(/(^'|'$)/g,"").replace(/''/g,"'")}),u}}function tr(){return function(e,t){return y(t)&&(t=2),G(e,t)}}function nr(){return function(e,t,n){return t=Math.abs(Number(t))===1/0?Number(t):p(t),isNaN(t)?e:(E(e)&&(e=e.toString()),Lr(e)||S(e)?(n=!n||isNaN(n)?0:p(n),n=n<0?Math.max(0,e.length+n):n,t>=0?e.slice(n,n+t):0===n?e.slice(t,e.length):e.slice(Math.max(0,n+t),n)):e)}}function rr(e){function t(t,n){return n=n?-1:1,t.map(function(t){var r=1,i=v;if(k(t))i=t;else if(S(t)&&("+"!=t.charAt(0)&&"-"!=t.charAt(0)||(r="-"==t.charAt(0)?-1:1,t=t.substring(1)),""!==t&&(i=e(t),i.constant))){var o=i();i=function(e){return e[o]}}return{get:i,descending:r*n}})}function n(e){switch(typeof e){case"number":case"boolean":case"string":return!0;default:return!1}}function r(e,t){return"function"==typeof e.valueOf&&(e=e.valueOf(),n(e))?e:g(e)&&(e=e.toString(),n(e))?e:t}function o(e,t){var n=typeof e;return null===e?(n="string",e="null"):"string"===n?e=e.toLowerCase():"object"===n&&(e=r(e,t)),{value:e,type:n}}function a(e,t){var n=0;return e.type===t.type?e.value!==t.value&&(n=e.value=v},s.$observe("min",function(e){v=p(e),u.$validate()})}if(b(s.max)||s.ngMax){var m;u.$validators.max=function(e){return!h(e)||y(m)||r(e)<=m},s.$observe("max",function(e){m=p(e),u.$validate()})}}}function pr(e,t,r,i){var o=t[0],a=i.$$hasNativeValidators=w(o.validity);a&&i.$parsers.push(function(e){var r=t.prop(Cr)||{};return r.badInput&&!r.typeMismatch?n:e})}function dr(e,t,r,i,o,a){if(pr(e,t,r,i),cr(e,t,r,i,o,a),i.$$parserName="number",i.$parsers.push(function(e){return i.$isEmpty(e)?null:_o.test(e)?parseFloat(e):n}),i.$formatters.push(function(e){if(!i.$isEmpty(e)){if(!E(e))throw ma("numfmt","Expected `{0}` to be a number",e);e=e.toString()}return e}),b(r.min)||r.ngMin){var s;i.$validators.min=function(e){return i.$isEmpty(e)||y(s)||e>=s},r.$observe("min",function(e){b(e)&&!E(e)&&(e=parseFloat(e,10)),s=E(e)&&!isNaN(e)?e:n,i.$validate()})}if(b(r.max)||r.ngMax){var u;i.$validators.max=function(e){return i.$isEmpty(e)||y(u)||e<=u},r.$observe("max",function(e){b(e)&&!E(e)&&(e=parseFloat(e,10)),u=E(e)&&!isNaN(e)?e:n,i.$validate()})}}function $r(e,t,n,r,i,o){cr(e,t,n,r,i,o),sr(r),r.$$parserName="url",r.$validators.url=function(e,t){var n=e||t;return r.$isEmpty(n)||Do.test(n)}}function vr(e,t,n,r,i,o){cr(e,t,n,r,i,o),sr(r),r.$$parserName="email",r.$validators.email=function(e,t){var n=e||t;return r.$isEmpty(n)||Po.test(n)}}function mr(e,t,n,r){y(n.name)&&t.attr("name",u());var i=function(e){t[0].checked&&r.$setViewValue(n.value,e&&e.type)};t.on("click",i),r.$render=function(){var e=n.value;t[0].checked=e==r.$viewValue},n.$observe("value",r.$render)}function gr(e,t,n,r,i){var o;if(b(r)){if(o=e(r),!o.constant)throw ma("constexpr","Expected constant expression for `{0}`, but saw `{1}`.",n,r);return o(t)}return i}function yr(e,t,n,r,i,o,a,s){var u=gr(s,e,"ngTrueValue",n.ngTrueValue,!0),c=gr(s,e,"ngFalseValue",n.ngFalseValue,!1),l=function(e){r.$setViewValue(t[0].checked,e&&e.type)};t.on("click",l),r.$render=function(){t[0].checked=r.$viewValue},r.$isEmpty=function(e){return e===!1},r.$formatters.push(function(e){return H(e,u)}),r.$parsers.push(function(e){return e?u:c})}function br(e,t){return e="ngClass"+e,["$animate",function(n){function r(e,t){var n=[];e:for(var r=0;r0||n[e])&&(n[e]=(n[e]||0)+t,n[e]===+(t>0)&&r.push(e))}),s.data("$classCounts",n),r.join(" ")}function h(e,t){var i=r(t,e),o=r(e,t);i=f(i,1),o=f(o,-1),i&&i.length&&n.addClass(s,i),o&&o.length&&n.removeClass(s,o)}function p(e){if(t===!0||a.$index%2===t){var n=i(e||[]);if(d){if(!H(e,d)){var r=i(d);h(r,n)}}else c(n)}d=Lr(e)?e.map(function(e){return F(e)}):F(e)}var d;a.$watch(u[e],p,!0),u.$observe("class",function(t){p(a.$eval(u[e]))}),"ngClass"!==e&&a.$watch("$index",function(n,r){var o=1&n;if(o!==(1&r)){var s=i(a.$eval(u[e]));o===t?c(s):l(s)}})}}}]}function wr(e){function t(e,t,u){y(t)?r("$pending",e,u):i("$pending",e,u),V(t)?t?(f(s.$error,e,u),l(s.$$success,e,u)):(l(s.$error,e,u),f(s.$$success,e,u)):(f(s.$error,e,u),f(s.$$success,e,u)),s.$pending?(o(va,!0),s.$valid=s.$invalid=n,a("",null)):(o(va,!1),s.$valid=xr(s.$error),s.$invalid=!s.$valid,a("",s.$valid));var c;c=s.$pending&&s.$pending[e]?n:!s.$error[e]&&(!!s.$$success[e]||null),a(e,c),s.$$parentForm.$setValidity(e,c,s)}function r(e,t,n){s[e]||(s[e]={}),l(s[e],t,n)}function i(e,t,r){s[e]&&f(s[e],t,r),xr(s[e])&&(s[e]=n)}function o(e,t){t&&!c[e]?(h.addClass(u,e),c[e]=!0):!t&&c[e]&&(h.removeClass(u,e),c[e]=!1)}function a(e,t){e=e?"-"+ce(e,"-"):"",o(la+e,t===!0),o(fa+e,t===!1)}var s=e.ctrl,u=e.$element,c={},l=e.set,f=e.unset,h=e.$animate;c[fa]=!(c[la]=u.hasClass(la)),s.$setValidity=t}function xr(e){if(e)for(var t in e)if(e.hasOwnProperty(t))return!1;return!0}function Sr(e){e[0].hasAttribute("selected")&&(e[0].selected=!0)}var Er=/^\/(.+)\/([a-z]*)$/,Cr="validity",kr=function(e){return S(e)?e.toLowerCase():e},Ar=Object.prototype.hasOwnProperty,Or=function(e){return S(e)?e.toUpperCase():e},Mr=function(e){return S(e)?e.replace(/[A-Z]/g,function(e){return String.fromCharCode(32|e.charCodeAt(0))}):e},Tr=function(e){return S(e)?e.replace(/[a-z]/g,function(e){return String.fromCharCode(e.charCodeAt(0)&-33)}):e};"i"!=="I".toLowerCase()&&(kr=Mr,Or=Tr);var Nr,jr,Vr,Dr,Pr=[].slice,_r=[].splice,Ir=[].push,Rr=Object.prototype.toString,qr=Object.getPrototypeOf,Ur=r("ng"),Fr=e.angular||(e.angular={}),Hr=0;Nr=t.documentMode,$.$inject=[],v.$inject=[];var Br,Lr=Array.isArray,zr=/^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/,Wr=function(e){return S(e)?e.trim():e},Gr=function(e){return e.replace(/([-()\[\]{}+?*.$\^|,:#(?:<\/\1>|)$/,vi=/<|&#?\w+;/,mi=/<([\w:-]+)/,gi=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,yi={option:[1,'"],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"], -_default:[0,"",""]};yi.optgroup=yi.option,yi.tbody=yi.tfoot=yi.colgroup=yi.caption=yi.thead,yi.th=yi.td;var bi=Node.prototype.contains||function(e){return!!(16&this.compareDocumentPosition(e))},wi=Me.prototype={ready:function(n){function r(){i||(i=!0,n())}var i=!1;"complete"===t.readyState?setTimeout(r):(this.on("DOMContentLoaded",r),Me(e).on("load",r))},toString:function(){var e=[];return o(this,function(t){e.push(""+t)}),"["+e.join(", ")+"]"},eq:function(e){return jr(e>=0?this[e]:this[this.length+e])},length:0,push:Ir,sort:[].sort,splice:[].splice},xi={};o("multiple,selected,checked,disabled,readOnly,required,open".split(","),function(e){xi[kr(e)]=e});var Si={};o("input,select,option,textarea,button,form,details".split(","),function(e){Si[e]=!0});var Ei={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};o({data:Pe,removeData:Ve,hasData:Ce},function(e,t){Me[t]=e}),o({data:Pe,inheritedData:Fe,scope:function(e){return jr.data(e,"$scope")||Fe(e.parentNode||e,["$isolateScope","$scope"])},isolateScope:function(e){return jr.data(e,"$isolateScope")||jr.data(e,"$isolateScopeNoTemplate")},controller:Ue,injector:function(e){return Fe(e,"$injector")},removeAttr:function(e,t){e.removeAttribute(t)},hasClass:_e,css:function(e,t,n){return t=xe(t),b(n)?void(e.style[t]=n):e.style[t]},attr:function(e,t,r){var i=e.nodeType;if(i!==ni&&i!==ti&&i!==ri){var o=kr(t);if(xi[o]){if(!b(r))return e[t]||(e.attributes.getNamedItem(t)||$).specified?o:n;r?(e[t]=!0,e.setAttribute(t,o)):(e[t]=!1,e.removeAttribute(o))}else if(b(r))e.setAttribute(t,r);else if(e.getAttribute){var a=e.getAttribute(t,2);return null===a?n:a}}},prop:function(e,t,n){return b(n)?void(e[t]=n):e[t]},text:function(){function e(e,t){if(y(t)){var n=e.nodeType;return n===ei||n===ni?e.textContent:""}e.textContent=t}return e.$dv="",e}(),val:function(e,t){if(y(t)){if(e.multiple&&"select"===R(e)){var n=[];return o(e.options,function(e){e.selected&&n.push(e.value||e.text)}),0===n.length?null:n}return e.value}e.value=t},html:function(e,t){return y(t)?e.innerHTML:(Ne(e,!0),void(e.innerHTML=t))},empty:He},function(e,t){Me.prototype[t]=function(t,n){var r,i,o=this.length;if(e!==He&&y(2==e.length&&e!==_e&&e!==Ue?t:n)){if(w(t)){for(r=0;r=0?t.split(" "):[t],c=u.length,l=function(t,n,i){var o=a[t];o||(o=a[t]=[],o.specialHandlerWrapper=n,"$destroy"===t||i||ci(e,t,s)),o.push(r)};c--;)t=u[c],pi[t]?(l(pi[t],Je),l(t,n,!0)):l(t)}},off:je,one:function(e,t,n){e=jr(e),e.on(t,function r(){e.off(t,n),e.off(t,r)}),e.on(t,n)},replaceWith:function(e,t){var n,r=e.parentNode;Ne(e),o(new Me(t),function(t){n?r.insertBefore(t,n.nextSibling):r.replaceChild(t,e),n=t})},children:function(e){var t=[];return o(e.childNodes,function(e){e.nodeType===ei&&t.push(e)}),t},contents:function(e){return e.contentDocument||e.childNodes||[]},append:function(e,t){var n=e.nodeType;if(n===ei||n===oi){t=new Me(t);for(var r=0,i=t.length;r1||e(function(){for(var e=0;e <= >= && || ! = |".split(" "),function(e){so[e]=!0});var uo={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},co=function(e){this.options=e};co.prototype={constructor:co,lex:function(e){for(this.text=e,this.index=0,this.tokens=[];this.index0&&!this.peek("}",")",";","]")&&e.push(this.expressionStatement()),!this.expect(";"))return{type:lo.Program,body:e}},expressionStatement:function(){return{type:lo.ExpressionStatement,expression:this.filterChain()}},filterChain:function(){for(var e,t=this.expression();e=this.expect("|");)t=this.filter(t);return t},expression:function(){return this.assignment()},assignment:function(){var e=this.ternary();return this.expect("=")&&(e={type:lo.AssignmentExpression,left:e,right:this.assignment(),operator:"="}),e},ternary:function(){var e,t,n=this.logicalOR();return this.expect("?")&&(e=this.expression(),this.consume(":"))?(t=this.expression(),{type:lo.ConditionalExpression,test:n,alternate:e,consequent:t}):n},logicalOR:function(){for(var e=this.logicalAND();this.expect("||");)e={type:lo.LogicalExpression,operator:"||",left:e,right:this.logicalAND()};return e},logicalAND:function(){for(var e=this.equality();this.expect("&&");)e={type:lo.LogicalExpression,operator:"&&",left:e,right:this.equality()};return e},equality:function(){for(var e,t=this.relational();e=this.expect("==","!=","===","!==");)t={type:lo.BinaryExpression,operator:e.text,left:t,right:this.relational()};return t},relational:function(){for(var e,t=this.additive();e=this.expect("<",">","<=",">=");)t={type:lo.BinaryExpression,operator:e.text,left:t,right:this.additive()};return t},additive:function(){for(var e,t=this.multiplicative();e=this.expect("+","-");)t={type:lo.BinaryExpression,operator:e.text,left:t,right:this.multiplicative()};return t},multiplicative:function(){for(var e,t=this.unary();e=this.expect("*","/","%");)t={type:lo.BinaryExpression,operator:e.text,left:t,right:this.unary()};return t},unary:function(){var e;return(e=this.expect("+","-","!"))?{type:lo.UnaryExpression,operator:e.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var e;this.expect("(")?(e=this.filterChain(),this.consume(")")):this.expect("[")?e=this.arrayDeclaration():this.expect("{")?e=this.object():this.constants.hasOwnProperty(this.peek().text)?e=U(this.constants[this.consume().text]):this.peek().identifier?e=this.identifier():this.peek().constant?e=this.constant():this.throwError("not a primary expression",this.peek());for(var t;t=this.expect("(","[",".");)"("===t.text?(e={type:lo.CallExpression,callee:e,arguments:this.parseArguments()},this.consume(")")):"["===t.text?(e={type:lo.MemberExpression,object:e,property:this.expression(),computed:!0},this.consume("]")):"."===t.text?e={type:lo.MemberExpression,object:e,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return e},filter:function(e){for(var t=[e],n={type:lo.CallExpression,callee:this.identifier(),arguments:t,filter:!0};this.expect(":");)t.push(this.expression());return n},parseArguments:function(){var e=[];if(")"!==this.peekToken().text)do e.push(this.expression());while(this.expect(","));return e},identifier:function(){var e=this.consume();return e.identifier||this.throwError("is not a valid identifier",e),{type:lo.Identifier,name:e.text}},constant:function(){return{type:lo.Literal,value:this.consume().value}},arrayDeclaration:function(){var e=[];if("]"!==this.peekToken().text)do{if(this.peek("]"))break;e.push(this.expression())}while(this.expect(","));return this.consume("]"),{type:lo.ArrayExpression,elements:e}},object:function(){var e,t=[];if("}"!==this.peekToken().text)do{if(this.peek("}"))break;e={type:lo.Property,kind:"init"},this.peek().constant?e.key=this.constant():this.peek().identifier?e.key=this.identifier():this.throwError("invalid key",this.peek()),this.consume(":"),e.value=this.expression(),t.push(e)}while(this.expect(","));return this.consume("}"),{type:lo.ObjectExpression,properties:t}},throwError:function(e,t){throw ro("syntax","Syntax Error: Token '{0}' {1} at column {2} of the expression [{3}] starting at [{4}].",t.text,e,t.index+1,this.text,this.text.substring(t.index))},consume:function(e){if(0===this.tokens.length)throw ro("ueoe","Unexpected end of expression: {0}",this.text);var t=this.expect(e);return t||this.throwError("is unexpected, expecting ["+e+"]",this.peek()),t},peekToken:function(){if(0===this.tokens.length)throw ro("ueoe","Unexpected end of expression: {0}",this.text);return this.tokens[0]},peek:function(e,t,n,r){return this.peekAhead(0,e,t,n,r)},peekAhead:function(e,t,n,r,i){if(this.tokens.length>e){var o=this.tokens[e],a=o.text;if(a===t||a===n||a===r||a===i||!t&&!n&&!r&&!i)return o}return!1},expect:function(e,t,n,r){var i=this.peek(e,t,n,r);return!!i&&(this.tokens.shift(),i)},constants:{true:{type:lo.Literal,value:!0},false:{type:lo.Literal,value:!1},null:{type:lo.Literal,value:null},undefined:{type:lo.Literal,value:n},this:{type:lo.ThisExpression}}},ln.prototype={compile:function(e,t){var r=this,i=this.astBuilder.ast(e);this.state={nextId:0,filters:{},expensiveChecks:t,fn:{vars:[],body:[],own:{}},assign:{vars:[],body:[],own:{}},inputs:[]},rn(i,r.$filter);var a,s="";if(this.stage="assign",a=sn(i)){this.state.computing="assign";var u=this.nextId();this.recurse(a,u),this.return_(u),s="fn.assign="+this.generateFunction("assign","s,v,l")}var c=on(i.body);r.stage="inputs",o(c,function(e,t){var n="fn"+t;r.state[n]={vars:[],body:[],own:{}},r.state.computing=n;var i=r.nextId();r.recurse(e,i),r.return_(i),r.state.inputs.push(n),e.watchId=t}),this.state.computing="fn",this.stage="main",this.recurse(i);var l='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+"var fn="+this.generateFunction("fn","s,l,a,i")+s+this.watchFns()+"return fn;",f=new Function("$filter","ensureSafeMemberName","ensureSafeObject","ensureSafeFunction","getStringValue","ensureSafeAssignContext","ifDefined","plus","text",l)(this.$filter,Jt,Zt,Kt,Xt,Qt,en,tn,e);return this.state=this.stage=n,f.literal=un(i),f.constant=cn(i),f},USE:"use",STRICT:"strict",watchFns:function(){var e=[],t=this.state.inputs,n=this;return o(t,function(t){e.push("var "+t+"="+n.generateFunction(t,"s"))}),t.length&&e.push("fn.inputs=["+t.join(",")+"];"),e.join("")},generateFunction:function(e,t){return"function("+t+"){"+this.varsPrefix(e)+this.body(e)+"};"},filterPrefix:function(){var e=[],t=this;return o(this.state.filters,function(n,r){e.push(n+"=$filter("+t.escape(r)+")")}),e.length?"var "+e.join(",")+";":""},varsPrefix:function(e){return this.state[e].vars.length?"var "+this.state[e].vars.join(",")+";":""},body:function(e){return this.state[e].body.join("")},recurse:function(e,t,r,i,a,s){var u,c,l,f,h=this;if(i=i||$,!s&&b(e.watchId))return t=t||this.nextId(),void this.if_("i",this.lazyAssign(t,this.computedMember("i",e.watchId)),this.lazyRecurse(e,t,r,i,a,!0));switch(e.type){case lo.Program:o(e.body,function(t,r){h.recurse(t.expression,n,n,function(e){c=e}),r!==e.body.length-1?h.current().body.push(c,";"):h.return_(c)});break;case lo.Literal:f=this.escape(e.value),this.assign(t,f),i(f);break;case lo.UnaryExpression:this.recurse(e.argument,n,n,function(e){c=e}),f=e.operator+"("+this.ifDefined(c,0)+")",this.assign(t,f),i(f);break;case lo.BinaryExpression:this.recurse(e.left,n,n,function(e){u=e}),this.recurse(e.right,n,n,function(e){c=e}),f="+"===e.operator?this.plus(u,c):"-"===e.operator?this.ifDefined(u,0)+e.operator+this.ifDefined(c,0):"("+u+")"+e.operator+"("+c+")",this.assign(t,f),i(f);break;case lo.LogicalExpression:t=t||this.nextId(),h.recurse(e.left,t),h.if_("&&"===e.operator?t:h.not(t),h.lazyRecurse(e.right,t)),i(t);break;case lo.ConditionalExpression:t=t||this.nextId(),h.recurse(e.test,t),h.if_(t,h.lazyRecurse(e.alternate,t),h.lazyRecurse(e.consequent,t)),i(t);break;case lo.Identifier:t=t||this.nextId(),r&&(r.context="inputs"===h.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",e.name)+"?l:s"),r.computed=!1,r.name=e.name),Jt(e.name),h.if_("inputs"===h.stage||h.not(h.getHasOwnProperty("l",e.name)),function(){h.if_("inputs"===h.stage||"s",function(){a&&1!==a&&h.if_(h.not(h.nonComputedMember("s",e.name)),h.lazyAssign(h.nonComputedMember("s",e.name),"{}")),h.assign(t,h.nonComputedMember("s",e.name))})},t&&h.lazyAssign(t,h.nonComputedMember("l",e.name))),(h.state.expensiveChecks||hn(e.name))&&h.addEnsureSafeObject(t),i(t);break;case lo.MemberExpression:u=r&&(r.context=this.nextId())||this.nextId(),t=t||this.nextId(),h.recurse(e.object,u,n,function(){h.if_(h.notNull(u),function(){a&&1!==a&&h.addEnsureSafeAssignContext(u),e.computed?(c=h.nextId(),h.recurse(e.property,c),h.getStringValue(c),h.addEnsureSafeMemberName(c),a&&1!==a&&h.if_(h.not(h.computedMember(u,c)),h.lazyAssign(h.computedMember(u,c),"{}")),f=h.ensureSafeObject(h.computedMember(u,c)),h.assign(t,f),r&&(r.computed=!0,r.name=c)):(Jt(e.property.name),a&&1!==a&&h.if_(h.not(h.nonComputedMember(u,e.property.name)),h.lazyAssign(h.nonComputedMember(u,e.property.name),"{}")),f=h.nonComputedMember(u,e.property.name),(h.state.expensiveChecks||hn(e.property.name))&&(f=h.ensureSafeObject(f)),h.assign(t,f),r&&(r.computed=!1,r.name=e.property.name))},function(){h.assign(t,"undefined")}),i(t)},!!a);break;case lo.CallExpression:t=t||this.nextId(),e.filter?(c=h.filter(e.callee.name),l=[],o(e.arguments,function(e){var t=h.nextId();h.recurse(e,t),l.push(t)}),f=c+"("+l.join(",")+")",h.assign(t,f),i(t)):(c=h.nextId(),u={},l=[],h.recurse(e.callee,c,u,function(){h.if_(h.notNull(c),function(){h.addEnsureSafeFunction(c),o(e.arguments,function(e){h.recurse(e,h.nextId(),n,function(e){l.push(h.ensureSafeObject(e))})}),u.name?(h.state.expensiveChecks||h.addEnsureSafeObject(u.context),f=h.member(u.context,u.name,u.computed)+"("+l.join(",")+")"):f=c+"("+l.join(",")+")",f=h.ensureSafeObject(f),h.assign(t,f)},function(){h.assign(t,"undefined")}),i(t)}));break;case lo.AssignmentExpression:if(c=this.nextId(),u={},!an(e.left))throw ro("lval","Trying to assign a value to a non l-value");this.recurse(e.left,n,u,function(){h.if_(h.notNull(u.context),function(){h.recurse(e.right,c),h.addEnsureSafeObject(h.member(u.context,u.name,u.computed)),h.addEnsureSafeAssignContext(u.context),f=h.member(u.context,u.name,u.computed)+e.operator+c,h.assign(t,f),i(t||f)})},1);break;case lo.ArrayExpression:l=[],o(e.elements,function(e){h.recurse(e,h.nextId(),n,function(e){l.push(e)})}),f="["+l.join(",")+"]",this.assign(t,f),i(f);break;case lo.ObjectExpression:l=[],o(e.properties,function(e){h.recurse(e.value,h.nextId(),n,function(t){l.push(h.escape(e.key.type===lo.Identifier?e.key.name:""+e.key.value)+":"+t)})}),f="{"+l.join(",")+"}",this.assign(t,f),i(f);break;case lo.ThisExpression:this.assign(t,"s"),i("s");break;case lo.NGValueParameter:this.assign(t,"v"),i("v")}},getHasOwnProperty:function(e,t){var n=e+"."+t,r=this.current().own;return r.hasOwnProperty(n)||(r[n]=this.nextId(!1,e+"&&("+this.escape(t)+" in "+e+")")),r[n]},assign:function(e,t){if(e)return this.current().body.push(e,"=",t,";"),e},filter:function(e){return this.state.filters.hasOwnProperty(e)||(this.state.filters[e]=this.nextId(!0)),this.state.filters[e]},ifDefined:function(e,t){return"ifDefined("+e+","+this.escape(t)+")"},plus:function(e,t){return"plus("+e+","+t+")"},return_:function(e){this.current().body.push("return ",e,";")},if_:function(e,t,n){if(e===!0)t();else{var r=this.current().body;r.push("if(",e,"){"),t(),r.push("}"),n&&(r.push("else{"),n(),r.push("}"))}},not:function(e){return"!("+e+")"},notNull:function(e){return e+"!=null"},nonComputedMember:function(e,t){return e+"."+t},computedMember:function(e,t){return e+"["+t+"]"},member:function(e,t,n){return n?this.computedMember(e,t):this.nonComputedMember(e,t)},addEnsureSafeObject:function(e){this.current().body.push(this.ensureSafeObject(e),";")},addEnsureSafeMemberName:function(e){this.current().body.push(this.ensureSafeMemberName(e),";")},addEnsureSafeFunction:function(e){this.current().body.push(this.ensureSafeFunction(e),";")},addEnsureSafeAssignContext:function(e){this.current().body.push(this.ensureSafeAssignContext(e),";")},ensureSafeObject:function(e){return"ensureSafeObject("+e+",text)"},ensureSafeMemberName:function(e){return"ensureSafeMemberName("+e+",text)"},ensureSafeFunction:function(e){return"ensureSafeFunction("+e+",text)"},getStringValue:function(e){this.assign(e,"getStringValue("+e+",text)")},ensureSafeAssignContext:function(e){return"ensureSafeAssignContext("+e+",text)"},lazyRecurse:function(e,t,n,r,i,o){var a=this;return function(){a.recurse(e,t,n,r,i,o)}},lazyAssign:function(e,t){var n=this;return function(){n.assign(e,t)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(e){return"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)},escape:function(e){if(S(e))return"'"+e.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(E(e))return e.toString();if(e===!0)return"true";if(e===!1)return"false";if(null===e)return"null";if("undefined"==typeof e)return"undefined";throw ro("esc","IMPOSSIBLE")},nextId:function(e,t){var n="v"+this.state.nextId++;return e||this.current().vars.push(n+(t?"="+t:"")),n},current:function(){return this.state[this.state.computing]}},fn.prototype={compile:function(e,t){var n=this,r=this.astBuilder.ast(e);this.expression=e,this.expensiveChecks=t,rn(r,n.$filter);var i,a;(i=sn(r))&&(a=this.recurse(i));var s,u=on(r.body);u&&(s=[],o(u,function(e,t){var r=n.recurse(e);e.input=r,s.push(r),e.watchId=t}));var c=[];o(r.body,function(e){c.push(n.recurse(e.expression))});var l=0===r.body.length?function(){}:1===r.body.length?c[0]:function(e,t){var n;return o(c,function(r){n=r(e,t)}),n};return a&&(l.assign=function(e,t,n){return a(e,n,t)}),s&&(l.inputs=s),l.literal=un(r),l.constant=cn(r),l},recurse:function(e,t,r){var i,a,s,u=this;if(e.input)return this.inputs(e.input,e.watchId);switch(e.type){case lo.Literal:return this.value(e.value,t);case lo.UnaryExpression:return a=this.recurse(e.argument),this["unary"+e.operator](a,t);case lo.BinaryExpression:return i=this.recurse(e.left),a=this.recurse(e.right),this["binary"+e.operator](i,a,t);case lo.LogicalExpression:return i=this.recurse(e.left),a=this.recurse(e.right),this["binary"+e.operator](i,a,t);case lo.ConditionalExpression:return this["ternary?:"](this.recurse(e.test),this.recurse(e.alternate),this.recurse(e.consequent),t);case lo.Identifier:return Jt(e.name,u.expression),u.identifier(e.name,u.expensiveChecks||hn(e.name),t,r,u.expression);case lo.MemberExpression:return i=this.recurse(e.object,!1,!!r),e.computed||(Jt(e.property.name,u.expression),a=e.property.name),e.computed&&(a=this.recurse(e.property)),e.computed?this.computedMember(i,a,t,r,u.expression):this.nonComputedMember(i,a,u.expensiveChecks,t,r,u.expression);case lo.CallExpression:return s=[],o(e.arguments,function(e){s.push(u.recurse(e))}),e.filter&&(a=this.$filter(e.callee.name)),e.filter||(a=this.recurse(e.callee,!0)),e.filter?function(e,r,i,o){for(var u=[],c=0;c":function(e,t,n){return function(r,i,o,a){var s=e(r,i,o,a)>t(r,i,o,a);return n?{value:s}:s}},"binary<=":function(e,t,n){return function(r,i,o,a){var s=e(r,i,o,a)<=t(r,i,o,a);return n?{value:s}:s}},"binary>=":function(e,t,n){return function(r,i,o,a){var s=e(r,i,o,a)>=t(r,i,o,a);return n?{value:s}:s}},"binary&&":function(e,t,n){return function(r,i,o,a){var s=e(r,i,o,a)&&t(r,i,o,a);return n?{value:s}:s}},"binary||":function(e,t,n){return function(r,i,o,a){var s=e(r,i,o,a)||t(r,i,o,a);return n?{value:s}:s}},"ternary?:":function(e,t,n,r){return function(i,o,a,s){var u=e(i,o,a,s)?t(i,o,a,s):n(i,o,a,s);return r?{value:u}:u}},value:function(e,t){return function(){return t?{context:n,name:n,value:e}:e}},identifier:function(e,t,r,i,o){return function(a,s,u,c){var l=s&&e in s?s:a;i&&1!==i&&l&&!l[e]&&(l[e]={});var f=l?l[e]:n;return t&&Zt(f,o),r?{context:l,name:e,value:f}:f}},computedMember:function(e,t,n,r,i){return function(o,a,s,u){var c,l,f=e(o,a,s,u);return null!=f&&(c=t(o,a,s,u),c=Xt(c),Jt(c,i),r&&1!==r&&(Qt(f),f&&!f[c]&&(f[c]={})),l=f[c],Zt(l,i)),n?{context:f,name:c,value:l}:l}},nonComputedMember:function(e,t,r,i,o,a){return function(s,u,c,l){var f=e(s,u,c,l);o&&1!==o&&(Qt(f),f&&!f[t]&&(f[t]={}));var h=null!=f?f[t]:n;return(r||hn(t))&&Zt(h,a),i?{context:f,name:t,value:h}:h}},inputs:function(e,t){return function(n,r,i,o){return o?o[t]:e(n,r,i)}}};var fo=function(e,t,n){this.lexer=e,this.$filter=t,this.options=n,this.ast=new lo(this.lexer),this.astCompiler=n.csp?new fn(this.ast,t):new ln(this.ast,t)};fo.prototype={constructor:fo,parse:function(e){return this.astCompiler.compile(e,this.options.expensiveChecks)}};var ho=Object.prototype.valueOf,po=r("$sce"),$o={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},Ui=r("$compile"),vo=t.createElement("a"),mo=Mn(e.location.href);jn.$inject=["$document"],Dn.$inject=["$provide"];var go=22,yo=".",bo="0";qn.$inject=["$locale"],Un.$inject=["$locale"];var wo={yyyy:zn("FullYear",4),yy:zn("FullYear",2,0,!0),y:zn("FullYear",1),MMMM:Wn("Month"),MMM:Wn("Month",!0),MM:zn("Month",2,1),M:zn("Month",1,1),dd:zn("Date",2),d:zn("Date",1),HH:zn("Hours",2),H:zn("Hours",1),hh:zn("Hours",2,-12),h:zn("Hours",1,-12),mm:zn("Minutes",2),m:zn("Minutes",1),ss:zn("Seconds",2),s:zn("Seconds",1),sss:zn("Milliseconds",3),EEEE:Wn("Day"),EEE:Wn("Day",!0),a:Zn,Z:Gn,ww:Xn(2),w:Xn(1),G:Kn,GG:Kn,GGG:Kn,GGGG:Qn},xo=/((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,So=/^\-?\d+$/;er.$inject=["$locale"];var Eo=m(kr),Co=m(Or);rr.$inject=["$parse"];var ko=m({restrict:"E",compile:function(e,t){if(!t.href&&!t.xlinkHref)return function(e,t){if("a"===t[0].nodeName.toLowerCase()){var n="[object SVGAnimatedString]"===Rr.call(t.prop("href"))?"xlink:href":"href";t.on("click",function(e){t.attr(n)||e.preventDefault()})}}}}),Ao={};o(xi,function(e,t){function n(e,n,i){e.$watch(i[r],function(e){i.$set(t,!!e)})}if("multiple"!=e){var r=ht("ng-"+t),i=n;"checked"===e&&(i=function(e,t,i){i.ngModel!==i[r]&&n(e,t,i)}),Ao[r]=function(){return{restrict:"A",priority:100,link:i}}}}),o(Ei,function(e,t){Ao[t]=function(){return{priority:100,link:function(e,n,r){if("ngPattern"===t&&"/"==r.ngPattern.charAt(0)){var i=r.ngPattern.match(Er);if(i)return void r.$set("ngPattern",new RegExp(i[1],i[2]))}e.$watch(r[t],function(e){r.$set(t,e)})}}}}),o(["src","srcset","href"],function(e){var t=ht("ng-"+e);Ao[t]=function(){return{priority:99,link:function(n,r,i){var o=e,a=e;"href"===e&&"[object SVGAnimatedString]"===Rr.call(r.prop("href"))&&(a="xlinkHref",i.$attr[a]="xlink:href",o=null),i.$observe(t,function(t){return t?(i.$set(a,t),void(Nr&&o&&r.prop(o,i[a]))):void("href"===e&&i.$set(a,null))})}}}});var Oo={$addControl:$,$$renameControl:or,$removeControl:$,$setValidity:$,$setDirty:$,$setPristine:$,$setSubmitted:$},Mo="ng-submitted";ar.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var To=function(e){return["$timeout","$parse",function(t,r){function i(e){return""===e?r('this[""]').assign:r(e).assign||$}var o={name:"form",restrict:e?"EAC":"E",require:["form","^^?form"],controller:ar,compile:function(r,o){r.addClass(ha).addClass(la);var a=o.name?"name":!(!e||!o.ngForm)&&"ngForm";return{pre:function(e,r,o,s){var u=s[0];if(!("action"in o)){var c=function(t){e.$apply(function(){u.$commitViewValue(),u.$setSubmitted()}),t.preventDefault()};ci(r[0],"submit",c),r.on("$destroy",function(){t(function(){li(r[0],"submit",c)},0,!1)})}var l=s[1]||u.$$parentForm;l.$addControl(u);var h=a?i(u.$name):$;a&&(h(e,u),o.$observe(a,function(t){u.$name!==t&&(h(e,n),u.$$parentForm.$$renameControl(u,t),(h=i(u.$name))(e,u))})),r.on("$destroy",function(){u.$$parentForm.$removeControl(u),h(e,n),f(u,Oo)})}}}};return o}]},No=To(),jo=To(!0),Vo=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/,Do=/^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:\/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i,Po=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,_o=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,Io=/^(\d{4})-(\d{2})-(\d{2})$/,Ro=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,qo=/^(\d{4})-W(\d\d)$/,Uo=/^(\d{4})-(\d\d)$/,Fo=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Ho="keydown wheel mousedown",Bo=ve();o("date,datetime-local,month,time,week".split(","),function(e){Bo[e]=!0});var Lo={text:ur,date:hr("date",Io,fr(Io,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":hr("datetimelocal",Ro,fr(Ro,["yyyy","MM","dd","HH","mm","ss","sss"]),"yyyy-MM-ddTHH:mm:ss.sss"),time:hr("time",Fo,fr(Fo,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:hr("week",qo,lr,"yyyy-Www"),month:hr("month",Uo,fr(Uo,["yyyy","MM"]),"yyyy-MM"),number:dr,url:$r,email:vr,radio:mr,checkbox:yr,hidden:$,button:$,submit:$,reset:$,file:$},zo=["$browser","$sniffer","$filter","$parse",function(e,t,n,r){return{restrict:"E",require:["?ngModel"],link:{pre:function(i,o,a,s){s[0]&&(Lo[kr(a.type)]||Lo.text)(i,o,a,s[0],t,e,n,r)}}}}],Wo=/^(true|false|\d+)$/,Go=function(){return{restrict:"A",priority:100,compile:function(e,t){return Wo.test(t.ngValue)?function(e,t,n){n.$set("value",e.$eval(n.ngValue))}:function(e,t,n){e.$watch(n.ngValue,function(e){n.$set("value",e)})}}}},Yo=["$compile",function(e){return{restrict:"AC",compile:function(t){return e.$$addBindingClass(t),function(t,n,r){e.$$addBindingInfo(n,r.ngBind),n=n[0],t.$watch(r.ngBind,function(e){n.textContent=y(e)?"":e})}}}}],Jo=["$interpolate","$compile",function(e,t){return{compile:function(n){return t.$$addBindingClass(n),function(n,r,i){var o=e(r.attr(i.$attr.ngBindTemplate));t.$$addBindingInfo(r,o.expressions),r=r[0],i.$observe("ngBindTemplate",function(e){r.textContent=y(e)?"":e})}}}}],Xo=["$sce","$parse","$compile",function(e,t,n){return{restrict:"A",compile:function(r,i){var o=t(i.ngBindHtml),a=t(i.ngBindHtml,function(t){return e.valueOf(t)});return n.$$addBindingClass(r),function(t,r,i){n.$$addBindingInfo(r,i.ngBindHtml),t.$watch(a,function(){var n=o(t);r.html(e.getTrustedHtml(n)||"")})}}}}],Zo=m({restrict:"A",require:"ngModel",link:function(e,t,n,r){r.$viewChangeListeners.push(function(){e.$eval(n.ngChange)})}}),Ko=br("",!0),Qo=br("Odd",0),ea=br("Even",1),ta=ir({compile:function(e,t){t.$set("ngCloak",n),e.removeClass("ng-cloak")}}),na=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],ra={},ia={blur:!0,focus:!0};o("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(e){var t=ht("ng-"+e);ra[t]=["$parse","$rootScope",function(n,r){return{restrict:"A",compile:function(i,o){var a=n(o[t],null,!0);return function(t,n){n.on(e,function(n){var i=function(){a(t,{$event:n})};ia[e]&&r.$$phase?t.$evalAsync(i):t.$apply(i)})}}}}]});var oa=["$animate",function(e){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(n,r,i,o,a){var s,u,c;n.$watch(i.ngIf,function(n){n?u||a(function(n,o){u=o,n[n.length++]=t.createComment(" end ngIf: "+i.ngIf+" "),s={clone:n},e.enter(n,r.parent(),r)}):(c&&(c.remove(),c=null),u&&(u.$destroy(),u=null),s&&(c=$e(s.clone),e.leave(c).then(function(){c=null}),s=null))})}}}],aa=["$templateRequest","$anchorScroll","$animate",function(e,t,n){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:Fr.noop,compile:function(r,i){var o=i.ngInclude||i.src,a=i.onload||"",s=i.autoscroll;return function(r,i,u,c,l){var f,h,p,d=0,$=function(){h&&(h.remove(),h=null),f&&(f.$destroy(),f=null),p&&(n.leave(p).then(function(){h=null}),h=p,p=null)};r.$watch(o,function(o){var u=function(){!b(s)||s&&!r.$eval(s)||t()},h=++d;o?(e(o,!0).then(function(e){if(!r.$$destroyed&&h===d){var t=r.$new();c.template=e;var s=l(t,function(e){$(),n.enter(e,null,i).then(u)});f=t,p=s,f.$emit("$includeContentLoaded",o),r.$eval(a)}},function(){r.$$destroyed||h===d&&($(),r.$emit("$includeContentError",o))}),r.$emit("$includeContentRequested",o)):($(),c.template=null)})}}}}],sa=["$compile",function(e){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(n,r,i,o){return/SVG/.test(r[0].toString())?(r.empty(),void e(ke(o.template,t).childNodes)(n,function(e){r.append(e)},{futureParentElement:r})):(r.html(o.template),void e(r.contents())(n))}}}],ua=ir({priority:450,compile:function(){return{pre:function(e,t,n){e.$eval(n.ngInit)}}}}),ca=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(e,t,r,i){var a=t.attr(r.$attr.ngList)||", ",s="false"!==r.ngTrim,u=s?Wr(a):a,c=function(e){if(!y(e)){var t=[];return e&&o(e.split(u),function(e){e&&t.push(s?Wr(e):e)}),t}};i.$parsers.push(c),i.$formatters.push(function(e){return Lr(e)?e.join(a):n}),i.$isEmpty=function(e){return!e||!e.length}}}},la="ng-valid",fa="ng-invalid",ha="ng-pristine",pa="ng-dirty",da="ng-untouched",$a="ng-touched",va="ng-pending",ma=r("ngModel"),ga=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(e,t,r,i,a,s,u,c,l,f){this.$viewValue=Number.NaN,this.$modelValue=Number.NaN,this.$$rawModelValue=n,this.$validators={},this.$asyncValidators={},this.$parsers=[],this.$formatters=[],this.$viewChangeListeners=[],this.$untouched=!0,this.$touched=!1,this.$pristine=!0,this.$dirty=!1,this.$valid=!0,this.$invalid=!1,this.$error={},this.$$success={},this.$pending=n,this.$name=f(r.name||"",!1)(e),this.$$parentForm=Oo;var h,p=a(r.ngModel),d=p.assign,v=p,m=d,g=null,w=this;this.$$setOptions=function(e){if(w.$options=e,e&&e.getterSetter){var t=a(r.ngModel+"()"),n=a(r.ngModel+"($$$p)");v=function(e){var n=p(e);return k(n)&&(n=t(e)),n},m=function(e,t){k(p(e))?n(e,{$$$p:w.$modelValue}):d(e,w.$modelValue)}}else if(!p.assign)throw ma("nonassign","Expression '{0}' is non-assignable. Element: {1}",r.ngModel,K(i))},this.$render=$,this.$isEmpty=function(e){return y(e)||""===e||null===e||e!==e};var x=0;wr({ctrl:this,$element:i,set:function(e,t){e[t]=!0},unset:function(e,t){delete e[t]},$animate:s}),this.$setPristine=function(){w.$dirty=!1,w.$pristine=!0,s.removeClass(i,pa),s.addClass(i,ha)},this.$setDirty=function(){w.$dirty=!0,w.$pristine=!1,s.removeClass(i,ha),s.addClass(i,pa),w.$$parentForm.$setDirty()},this.$setUntouched=function(){w.$touched=!1,w.$untouched=!0,s.setClass(i,da,$a)},this.$setTouched=function(){w.$touched=!0,w.$untouched=!1,s.setClass(i,$a,da)},this.$rollbackViewValue=function(){u.cancel(g),w.$viewValue=w.$$lastCommittedViewValue,w.$render()},this.$validate=function(){if(!E(w.$modelValue)||!isNaN(w.$modelValue)){var e=w.$$lastCommittedViewValue,t=w.$$rawModelValue,r=w.$valid,i=w.$modelValue,o=w.$options&&w.$options.allowInvalid;w.$$runValidators(t,e,function(e){o||r===e||(w.$modelValue=e?t:n,w.$modelValue!==i&&w.$$writeModelToScope())})}},this.$$runValidators=function(e,t,r){function i(){var e=w.$$parserName||"parse";return y(h)?(u(e,null),!0):(h||(o(w.$validators,function(e,t){u(t,null)}),o(w.$asyncValidators,function(e,t){u(t,null)})),u(e,h),h)}function a(){var n=!0;return o(w.$validators,function(r,i){var o=r(e,t);n=n&&o,u(i,o)}),!!n||(o(w.$asyncValidators,function(e,t){u(t,null)}),!1)}function s(){var r=[],i=!0;o(w.$asyncValidators,function(o,a){var s=o(e,t);if(!D(s))throw ma("nopromise","Expected asynchronous validator to return a promise but got '{0}' instead.",s);u(a,n),r.push(s.then(function(){u(a,!0)},function(e){i=!1,u(a,!1)}))}),r.length?l.all(r).then(function(){c(i)},$):c(!0)}function u(e,t){f===x&&w.$setValidity(e,t)}function c(e){f===x&&r(e)}x++;var f=x;return i()&&a()?void s():void c(!1)},this.$commitViewValue=function(){var e=w.$viewValue;u.cancel(g),(w.$$lastCommittedViewValue!==e||""===e&&w.$$hasNativeValidators)&&(w.$$lastCommittedViewValue=e,w.$pristine&&this.$setDirty(),this.$$parseAndValidate())},this.$$parseAndValidate=function(){function t(){w.$modelValue!==a&&w.$$writeModelToScope()}var r=w.$$lastCommittedViewValue,i=r;if(h=!y(i)||n)for(var o=0;o0&&(e=new RegExp("^"+e+"$")),e&&!e.test)throw r("ngPattern")("noregexp","Expected {0} to be a RegExp but was {1}. Element: {2}",s,e,K(t));a=e||n,o.$validate()}),o.$validators.pattern=function(e,t){return o.$isEmpty(t)||y(a)||a.test(t)}}}}},za=function(){return{restrict:"A",require:"?ngModel",link:function(e,t,n,r){if(r){var i=-1;n.$observe("maxlength",function(e){var t=p(e);i=isNaN(t)?-1:t,r.$validate()}),r.$validators.maxlength=function(e,t){return i<0||r.$isEmpty(t)||t.length<=i}}}}},Wa=function(){return{restrict:"A",require:"?ngModel",link:function(e,t,n,r){if(r){var i=0;n.$observe("minlength",function(e){i=p(e)||0,r.$validate()}),r.$validators.minlength=function(e,t){return r.$isEmpty(t)||t.length>=i}}}}};return e.angular.bootstrap?void(e.console&&console.log("WARNING: Tried to load angular more than once.")):(le(),be(Fr),Fr.module("ngLocale",[],["$provide",function(e){function t(e){e+="";var t=e.indexOf(".");return t==-1?0:e.length-t-1}function r(e,r){var i=r;n===i&&(i=Math.min(t(e),3));var o=Math.pow(10,i),a=(e*o|0)%o;return{v:i,f:a}}var i={ZERO:"zero",ONE:"one",TWO:"two",FEW:"few",MANY:"many",OTHER:"other"};e.value("$locale",{DATETIME_FORMATS:{AMPMS:["AM","PM"],DAY:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"],FIRSTDAYOFWEEK:6,MONTH:["January","February","March","April","May","June","July","August","September","October","November","December"],SHORTDAY:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],SHORTMONTH:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],STANDALONEMONTH:["January","February","March","April","May","June","July","August","September","October","November","December"],WEEKENDRANGE:[5,6],fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",medium:"MMM d, y h:mm:ss a",mediumDate:"MMM d, y",mediumTime:"h:mm:ss a",short:"M/d/yy h:mm a",shortDate:"M/d/yy",shortTime:"h:mm a"},NUMBER_FORMATS:{CURRENCY_SYM:"$",DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{gSize:3,lgSize:3,maxFrac:3,minFrac:0,minInt:1,negPre:"-",negSuf:"",posPre:"",posSuf:""},{gSize:3,lgSize:3,maxFrac:2,minFrac:2,minInt:1,negPre:"-¤",negSuf:"",posPre:"¤",posSuf:""}]},id:"en-us",localeID:"en_US",pluralCat:function(e,t){var n=0|e,o=r(e,t);return 1==n&&0==o.v?i.ONE:i.OTHER}})}]),void jr(t).ready(function(){oe(t,ae)}))}(window,document),!window.angular.$$csp().noInlineStyle&&window.angular.element(document.head).prepend('')},function(e,t,n){n(5),e.exports="ngRoute"},function(e,t){/** - * @license AngularJS v1.4.14 - * (c) 2010-2015 Google, Inc. http://angularjs.org - * License: MIT - */ -!function(e,t,n){"use strict";function r(){function e(e,n){return t.extend(Object.create(e),n)}function n(e,t){var n=t.caseInsensitiveMatch,r={originalPath:e,regexp:e},i=r.keys=[];return e=e.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)(\*\?|[\?\*])?/g,function(e,t,n,r){var o="?"===r||"*?"===r?"?":null,a="*"===r||"*?"===r?"*":null;return i.push({name:n,optional:!!o}),t=t||"",""+(o?"":t)+"(?:"+(o?t:"")+(a&&"(.+?)"||"([^/]+)")+(o||"")+")"+(o||"")}).replace(/([\/$\*])/g,"\\$1"),r.regexp=new RegExp("^"+e+"$",n?"i":""),r}var r={};this.when=function(e,i){var o=t.copy(i);if(t.isUndefined(o.reloadOnSearch)&&(o.reloadOnSearch=!0),t.isUndefined(o.caseInsensitiveMatch)&&(o.caseInsensitiveMatch=this.caseInsensitiveMatch),r[e]=t.extend(o,e&&n(e,o)),e){var a="/"==e[e.length-1]?e.substr(0,e.length-1):e+"/";r[a]=t.extend({redirectTo:e},n(a,o))}return this},this.caseInsensitiveMatch=!1,this.otherwise=function(e){return"string"==typeof e&&(e={redirectTo:e}),this.when(null,e),this},this.$get=["$rootScope","$location","$routeParams","$q","$injector","$templateRequest","$sce",function(n,i,o,a,s,c,l){function f(e,t){var n=t.keys,r={};if(!t.regexp)return null;var i=t.regexp.exec(e);if(!i)return null;for(var o=1,a=i.length;o=0&&y[o]!=r;o--);if(o>=0){for(i=y.length-1;i>=o;i--)n.end&&n.end(y[i]);y.length=o}}"string"!=typeof e&&(e=null===e||"undefined"==typeof e?"":""+e);var o,a,u,c,y=[],b=e;for(y.last=function(){return y[y.length-1]};e;){if(c="",a=!0,y.last()&&O[y.last()]?(e=e.replace(new RegExp("([\\W\\w]*)<\\s*\\/\\s*"+y.last()+"[^>]*>","i"),function(e,t){return t=t.replace(v,"$1").replace(g,"$1"),n.chars&&n.chars(s(t)),""}),i("",y.last())):(0===e.indexOf("",o)===o&&(n.comment&&n.comment(e.substring(4,o)),e=e.substring(o+3),a=!1)):m.test(e)?(u=e.match(m),u&&(e=e.replace(u[0],""),a=!1)):$.test(e)?(u=e.match(h),u&&(e=e.substring(u[0].length),u[0].replace(h,i),a=!1)):d.test(e)&&(u=e.match(f),u?(u[4]&&(e=e.substring(u[0].length),u[0].replace(f,r)),a=!1):(c+="<",e=e.substring(1))),a&&(o=e.indexOf("<"),c+=o<0?e:e.substring(0,o),e=o<0?"":e.substring(o),n.chars&&n.chars(s(c)))),e==b)throw l("badparse","The sanitizer was unable to parse the following block of html: {0}",e);b=e}i()}function s(e){return e?(D.innerHTML=e.replace(//g,">")}function c(e,n){var r=!1,i=t.bind(e,e.push);return{start:function(e,o,a){e=t.lowercase(e),!r&&O[e]&&(r=e),r||M[e]!==!0||(i("<"),i(e),t.forEach(o,function(r,o){var a=t.lowercase(o),s="img"===e&&"src"===a||"background"===a;V[a]!==!0||T[a]===!0&&!n(r,s)||(i(" "),i(o),i('="'),i(u(r)),i('"'))}),i(a?"/>":">"))},end:function(e){e=t.lowercase(e),r||M[e]!==!0||(i("")),e==r&&(r=!1)},chars:function(e){r||i(u(e))}}}var l=t.$$minErr("$sanitize"),f=/^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,h=/^<\/\s*([\w:-]+)[^>]*>/,p=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,d=/^/g,m=/]*?)>/i,g=//g,y=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,b=/([^\#-~| |!])/g,w=o("area,br,col,hr,img,wbr"),x=o("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),S=o("rp,rt"),E=t.extend({},S,x),C=t.extend({},x,o("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),k=t.extend({},S,o("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")),A=o("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,stop,svg,switch,text,title,tspan,use"),O=o("script,style"),M=t.extend({},w,C,k,E,A),T=o("background,cite,href,longdesc,src,usemap,xlink:href"),N=o("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,valign,value,vspace,width"),j=o("accent-height,accumulate,additive,alphabetic,arabic-form,ascent,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan",!0),V=t.extend({},T,j,N),D=document.createElement("pre");t.module("ngSanitize",[]).provider("$sanitize",r),t.module("ngSanitize").filter("linky",["$sanitize",function(e){var n=/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,r=/^mailto:/i;return function(o,a){function s(e){e&&p.push(i(e))}function u(e,n){p.push("'),s(n),p.push("")}if(!o)return o;for(var c,l,f,h=o,p=[];c=h.match(n);)l=c[0],c[2]||c[4]||(l=(c[3]?"http://":"mailto:")+l),f=c.index,s(h.substr(0,f)),u(l,c[0].replace(r,"")),h=h.substring(f+c[0].length);return s(h),e(p.join(""))}}])}(window,window.angular)},function(e,t,n){n(9),e.exports="ngTouch"},function(e,t){/** - * @license AngularJS v1.4.14 - * (c) 2010-2015 Google, Inc. http://angularjs.org - * License: MIT - */ -!function(e,t,n){"use strict";function r(e){return t.lowercase(e.nodeName||e[0]&&e[0].nodeName)}function i(e,n,r){o.directive(e,["$parse","$swipe",function(i,o){var a=75,s=.3,u=30;return function(c,l,f){function h(e){if(!p)return!1;var t=Math.abs(e.y-p.y),r=(e.x-p.x)*n;return d&&t0&&r>u&&t/ra?(l=!1,void(i.cancel&&i.cancel(t))):(t.preventDefault(),void(i.move&&i.move(n,t)))}}),t.on(n(o,"end"),function(t){l&&(l=!1,i.end&&i.end(e(t),t))})}}}]),o.config(["$provide",function(e){e.decorator("ngClickDirective",["$delegate",function(e){return e.shift(),e}])}]),o.directive("ngClick",["$parse","$timeout","$rootElement",function(e,n,i){function o(e,t,n,r){return Math.abs(e-n)$)){var t=e.touches&&e.touches.length?e.touches:[e],n=t[0].clientX,i=t[0].clientY;n<1&&i<1||h&&h[0]===n&&h[1]===i||(h&&(h=null),"label"===r(e.target)&&(h=[n,i]),a(f,n,i)||(e.stopPropagation(),e.preventDefault(),e.target&&e.target.blur&&e.target.blur()))}}function u(e){var t=e.touches&&e.touches.length?e.touches:[e],r=t[0].clientX,i=t[0].clientY;f.push(r,i),n(function(){for(var e=0;e\n

\n

{{ui.heading}} {{ui.message}}

\n

Possible reasons are:

\n
    \n
  • 1. Your process was exited by another tool
  • \n
\n

You should check your terminal window to see what happened.
(Or simply try reloading this page.)

\n',controller:["$scope","$rootScope","$window",e]}})}(angular)},function(e,t){!function(e){function t(e,t){var n="info",r="Browsersync:",i="Welcome to Browsersync",o=2e3;e.ui={status:n,heading:r,message:i},e.show=function(t,i){i=i||{},e._timer&&clearTimeout(e._timer),e._timer=window.setTimeout(e.reset,i.timeout||o),e.ui.visible=!0,e.ui.status=i.status||n,e.ui.heading=i.heading||r,e.ui.message=i.message||r},e.reset=function(){e.ui.visible=!1,e.$digest()},t.$on("notify:flash",e.show)}e.module("bsNotify",[]).directive("notifyElem",function(){return{restrict:"E",scope:{},template:'
\n

{{ui.heading}} {{ui.message}}

\n
',controller:["$scope","$rootScope",t]}})}(angular)},function(e,t){!function(e){function t(e){var t=[],n=[];return e.on("ui:history:update",function(e){n.forEach(function(t){t(e)})}),{visited:t,updateHistory:function(e){t=e},get:function(){return e.getData("visited")},remove:function(t){e.emit("ui",{namespace:"history",event:"remove",data:t})},clear:function(){e.emit("ui",{namespace:"history",event:"clear"})},on:function(e,t){n.push(t)},off:function(e){var t=n.indexOf(e);t>-1&&(n=n.splice(t,1))}}}e.module("bsHistory",["bsSocket"]).service("History",["Socket",t])}(angular)},function(e,t){!function(e){function t(e){var t={reloadAll:function(){e.clientEvent("browser:reload")},sendAllTo:function(t){e.emit("ui",{namespace:"history",event:"sendAllTo",data:{path:t}})},scrollAllTo:function(){e.clientEvent("scroll",{position:{raw:0,proportional:0},override:!0})},highlight:function(t){e.emit("ui:highlight",t)}};return t}e.module("bsClients",["bsSocket"]).service("Clients",["Socket",t])}(angular)},function(e,t){!function(e,t){function n(e,t){var n,i=e.defer();r.on("connection",function(e){if(n=e.session,t.$emit("ui:connection",e),i.resolve(e,this),""===window.name)window.name=JSON.stringify({id:r.id});else{var o=JSON.parse(window.name);o.id!==r.id}}),r.on("disconnect",function(){t.$emit("ui:disconnect")});var o={on:function(e,t){r.on(e,t)},off:function(e,t){r.off(e,t)},removeEvent:function(e,t){r.removeListener(e,t)},emit:function(e,t){r.emit(e,t||{})},clientEvent:function(e,t){r.emit("ui:client:proxy",{event:e,data:t})},options:function(){return i.promise},getData:function(t){var n=e.defer();return r.on("ui:receive:"+t,function(e){n.resolve(e)}),r.emit("ui:get:"+t),n.promise},uiEvent:function(e){r.emit("ui",e)},newSession:function(){}};return Object.defineProperty(o,"sessionId",{get:function(){return n}}),o}var r=t||{emit:function(){},on:function(){},removeListener:function(){}};e.module("bsSocket",[]).service("Socket",["$q","$rootScope",n])}(angular,window.___browserSync___.socket)},function(e,t,n){function r(e,t){return{enable:function(t){return angular.forEach(e,function(e){e.active=!1}),t.active=!0,e},transform:function(e,t){if("function"==typeof t)return e=t(e);throw new TypeError("Noooo")},current:function(){if("/"===t.path())return e.overview;var n;return angular.forEach(e,function(e){e.path===t.path()&&(n=e)}),n}}}var i=n(16);i.service("Pages",["pagesConfig","$location",r])},function(e,t){e.exports=window.angular.module("BrowserSync")},function(e,t,n){function r(e){return{all:function(){return e.getData("options")}}}var i=n(16);i.factory("Options",["Socket",r])},function(e,t,n){function r(e){var t=a.get("bs",{});Object.keys(t).length||a.set("bs",{}),this.ns=e,this.get=function(t){var n=a.get("bs",{});return Object.keys(n).length||a.set("bs",{}),s.get(n,[e].concat(t).join("."))},this.set=function(t,n){var r=a.get("bs",{});Object.keys(r).length||a.set("bs",{}),r[e]||(r[e]={}),r[e][t]=n,a.set("bs",r)},this.remove=function(t){var n=a.get("bs",{});Object.keys(n).length||a.set("bs",{}),n[e]||(n[e]={}),n[e][t]&&delete n[e][t],a.set("bs",n)}}function i(){return{create:function(e){var t=new r(e);return t}}}var o=n(19),a=n(20),s=n(21);o.module("bsStore",[]).service("Store",["$q","$rootScope",i])},function(e,t){e.exports=window.angular},function(e,t,n){var r,i,o;(function(n){"use strict";!function(n,a){i=[],r=a,o="function"==typeof r?r.apply(t,i):r,!(void 0!==o&&(e.exports=o))}(this,function(){function e(){try{return a in i&&i[a]}catch(e){return!1}}var t,r={},i="undefined"!=typeof window?window:n,o=i.document,a="localStorage",s="script";if(r.disabled=!1,r.version="1.3.20",r.set=function(e,t){},r.get=function(e,t){},r.has=function(e){return void 0!==r.get(e)},r.remove=function(e){},r.clear=function(){},r.transact=function(e,t,n){null==n&&(n=t,t=null),null==t&&(t={});var i=r.get(e,t);n(i),r.set(e,i)},r.getAll=function(){},r.forEach=function(){},r.serialize=function(e){return JSON.stringify(e)},r.deserialize=function(e){if("string"==typeof e)try{return JSON.parse(e)}catch(t){return e||void 0}},e())t=i[a],r.set=function(e,n){return void 0===n?r.remove(e):(t.setItem(e,r.serialize(n)),n)},r.get=function(e,n){var i=r.deserialize(t.getItem(e));return void 0===i?n:i},r.remove=function(e){t.removeItem(e)},r.clear=function(){t.clear()},r.getAll=function(){var e={};return r.forEach(function(t,n){e[t]=n}),e},r.forEach=function(e){for(var n=0;ndocument.w=window'),c.close(),u=c.w.frames[0].document,t=u.createElement("div")}catch(e){t=o.createElement("div"),u=o.body}var l=function(e){return function(){var n=Array.prototype.slice.call(arguments,0);n.unshift(t),u.appendChild(t),t.addBehavior("#default#userData"),t.load(a);var i=e.apply(r,n);return u.removeChild(t),i}},f=new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]","g"),h=function(e){return e.replace(/^d/,"___$&").replace(f,"___")};r.set=l(function(e,t,n){return t=h(t),void 0===n?r.remove(t):(e.setAttribute(t,r.serialize(n)),e.save(a),n)}),r.get=l(function(e,t,n){t=h(t);var i=r.deserialize(e.getAttribute(t));return void 0===i?n:i}),r.remove=l(function(e,t){t=h(t),e.removeAttribute(t),e.save(a)}),r.clear=l(function(e){var t=e.XMLDocument.documentElement.attributes;e.load(a);for(var n=t.length-1;n>=0;n--)e.removeAttribute(t[n].name);e.save(a)}),r.getAll=function(e){var t={};return r.forEach(function(e,n){t[e]=n}),t},r.forEach=l(function(e,t){for(var n,i=e.XMLDocument.documentElement.attributes,o=0;n=i[o];++o)t(n.name,r.deserialize(e.getAttribute(n.name)))})}try{var p="__storejs__";r.set(p,p),r.get(p)!=p&&(r.disabled=!0),r.remove(p)}catch(e){r.disabled=!0}return r.enabled=!r.disabled,r})}).call(t,function(){return this}())},function(e,t,n){var r,i,o;!function(n,a){"use strict";"object"==typeof e&&"object"==typeof e.exports?e.exports=a():(i=[],r=a,o="function"==typeof r?r.apply(t,i):r,!(void 0!==o&&(e.exports=o)))}(this,function(){"use strict";function e(e){if(!e)return!0;if(o(e)&&0===e.length)return!0;if(!r(e)){for(var t in e)if(f.call(e,t))return!1;return!0}return!1}function t(e){return l.call(e)}function n(e){return"number"==typeof e||"[object Number]"===t(e)}function r(e){return"string"==typeof e||"[object String]"===t(e)}function i(e){return"object"==typeof e&&"[object Object]"===t(e)}function o(e){return"object"==typeof e&&"number"==typeof e.length&&"[object Array]"===t(e)}function a(e){return"boolean"==typeof e||"[object Boolean]"===t(e)}function s(e){var t=parseInt(e);return t.toString()===e?t:e}function u(t,i,o,a){if(n(i)&&(i=[i]),e(i))return t;if(r(i))return u(t,i.split(".").map(s),o,a);var c=i[0];if(1===i.length){var l=t[c];return void 0!==l&&a||(t[c]=o),l}return void 0===t[c]&&(n(i[1])?t[c]=[]:t[c]={}),u(t[c],i.slice(1),o,a)}function c(t,i){if(n(i)&&(i=[i]),!e(t)){if(e(i))return t;if(r(i))return c(t,i.split("."));var a=s(i[0]),u=t[a];if(1===i.length)void 0!==u&&(o(t)?t.splice(a,1):delete t[a]);else if(void 0!==t[a])return c(t[a],i.slice(1));return t}}var l=Object.prototype.toString,f=Object.prototype.hasOwnProperty,h=function(e){return Object.keys(h).reduce(function(t,n){return"function"==typeof h[n]&&(t[n]=h[n].bind(h,e)),t},{})};return h.has=function(t,a){if(e(t))return!1;if(n(a)?a=[a]:r(a)&&(a=a.split(".")),e(a)||0===a.length)return!1;for(var s=0;sn[t]?1:-1}),n&&r.reverse(),r}}},function(e,t,n){var e=n(16);e.directive("icon",n(26)),e.directive("linkTo",n(27)),e.directive("switch",n(28)),e.directive("newTab",n(29))},function(e,t){e.exports=function(){return{scope:{icon:"@"},restrict:"E",replace:!0,template:'',link:function(e,t,n){return e.iconName="#svg-"+e.icon,e}}}},function(e,t){e.exports=function(){return{restrict:"E",replace:!1,transclude:!0,scope:{path:"@"},template:"as",controller:["$scope","$location","$injector",function(e,t,n){var r=n.get("pagesConfig"),i=n.get("Pages");e.navi=function(e){var n=r[e];i.enable(n),t.path(e)}}]}}},function(e,t){e.exports=function(){return{scope:{toggle:"&",item:"=",switchid:"@",title:"@",tagline:"@",active:"=",prop:"@"},restrict:"E",replace:!0,transclude:!0,templateUrl:"bs-switch.html",controllerAs:"ctrl",controller:["$scope",function(e){var t=this;t.item=e.item}]}}},function(e,t){e.exports=function(){return{scope:{url:"@",mode:"@"},restrict:"E",replace:!0,template:' New Tab '}}}]); \ No newline at end of file diff --git a/web/node_modules/browser-sync-ui/public/js/app.js.map b/web/node_modules/browser-sync-ui/public/js/app.js.map deleted file mode 100644 index 86bfa77..0000000 --- a/web/node_modules/browser-sync-ui/public/js/app.js.map +++ /dev/null @@ -1,63 +0,0 @@ -{ - "version": 3, - "sources": [ - "node_modules/browserify/node_modules/browser-pack/_prelude.js", - "src/scripts/app.js", - "node_modules/angular-route/angular-route.js", - "node_modules/angular-sanitize/angular-sanitize.js", - "node_modules/angular-touch/angular-touch.js", - "node_modules/angular/angular.js", - "node_modules/object-path/index.js", - "node_modules/store/store.js", - "src/scripts/angular.js", - "src/scripts/directives.js", - "src/scripts/directives/icon.js", - "src/scripts/directives/link-to.js", - "src/scripts/directives/new-tab.js", - "src/scripts/directives/switch.js", - "src/scripts/filters.js", - "src/scripts/main/controller.js", - "src/scripts/module.js", - "src/scripts/modules/bsClients.js", - "src/scripts/modules/bsDisconnect.js", - "src/scripts/modules/bsHistory.js", - "src/scripts/modules/bsNotify.js", - "src/scripts/modules/bsSocket.js", - "src/scripts/modules/bsStore.js", - "src/scripts/services/Options.js", - "src/scripts/services/Pages.js", - "src/scripts/utils.js" - ], - "names": [], - "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACn+BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxqBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9mBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACngzBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/KA;AACA;AACA;AACA;AACA;;ACJA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9JA;AACA;AACA;AACA;AACA;;ACJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", - "file": "generated.js", - "sourceRoot": "", - "sourcesContent": [ - "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o
\n */\n /* global -ngRouteModule */\nvar ngRouteModule = angular.module('ngRoute', ['ng']).\n provider('$route', $RouteProvider),\n $routeMinErr = angular.$$minErr('ngRoute');\n\n/**\n * @ngdoc provider\n * @name $routeProvider\n *\n * @description\n *\n * Used for configuring routes.\n *\n * ## Example\n * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.\n *\n * ## Dependencies\n * Requires the {@link ngRoute `ngRoute`} module to be installed.\n */\nfunction $RouteProvider() {\n function inherit(parent, extra) {\n return angular.extend(Object.create(parent), extra);\n }\n\n var routes = {};\n\n /**\n * @ngdoc method\n * @name $routeProvider#when\n *\n * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n * contains redundant trailing slash or is missing one, the route will still match and the\n * `$location.path` will be updated to add or drop the trailing slash to exactly match the\n * route definition.\n *\n * * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up\n * to the next slash are matched and stored in `$routeParams` under the given `name`\n * when the route matches.\n * * `path` can contain named groups starting with a colon and ending with a star:\n * e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`\n * when the route matches.\n * * `path` can contain optional named groups with a question mark: e.g.`:name?`.\n *\n * For example, routes like `/color/:color/largecode/:largecode*\\/edit` will match\n * `/color/brown/largecode/code/with/slashes/edit` and extract:\n *\n * * `color: brown`\n * * `largecode: code/with/slashes`.\n *\n *\n * @param {Object} route Mapping information to be assigned to `$route.current` on route\n * match.\n *\n * Object properties:\n *\n * - `controller` – `{(string|function()=}` – Controller fn that should be associated with\n * newly created scope or the name of a {@link angular.Module#controller registered\n * controller} if passed as a string.\n * - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be\n * published to scope under the `controllerAs` name.\n * - `template` – `{string=|function()=}` – html template as a string or a function that\n * returns an html template as a string which should be used by {@link\n * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.\n * This property takes precedence over `templateUrl`.\n *\n * If `template` is a function, it will be called with the following parameters:\n *\n * - `{Array.}` - route parameters extracted from the current\n * `$location.path()` by applying the current route\n *\n * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html\n * template that should be used by {@link ngRoute.directive:ngView ngView}.\n *\n * If `templateUrl` is a function, it will be called with the following parameters:\n *\n * - `{Array.}` - route parameters extracted from the current\n * `$location.path()` by applying the current route\n *\n * - `resolve` - `{Object.=}` - An optional map of dependencies which should\n * be injected into the controller. If any of these dependencies are promises, the router\n * will wait for them all to be resolved or one to be rejected before the controller is\n * instantiated.\n * If all the promises are resolved successfully, the values of the resolved promises are\n * injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is\n * fired. If any of the promises are rejected the\n * {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object\n * is:\n *\n * - `key` – `{string}`: a name of a dependency to be injected into the controller.\n * - `factory` - `{string|function}`: If `string` then it is an alias for a service.\n * Otherwise if function, then it is {@link auto.$injector#invoke injected}\n * and the return value is treated as the dependency. If the result is a promise, it is\n * resolved before its value is injected into the controller. Be aware that\n * `ngRoute.$routeParams` will still refer to the previous route within these resolve\n * functions. Use `$route.current.params` to access the new route parameters, instead.\n *\n * - `redirectTo` – {(string|function())=} – value to update\n * {@link ng.$location $location} path with and trigger route redirection.\n *\n * If `redirectTo` is a function, it will be called with the following parameters:\n *\n * - `{Object.}` - route parameters extracted from the current\n * `$location.path()` by applying the current route templateUrl.\n * - `{string}` - current `$location.path()`\n * - `{Object}` - current `$location.search()`\n *\n * The custom `redirectTo` function is expected to return a string which will be used\n * to update `$location.path()` and `$location.search()`.\n *\n * - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()`\n * or `$location.hash()` changes.\n *\n * If the option is set to `false` and url in the browser changes, then\n * `$routeUpdate` event is broadcasted on the root scope.\n *\n * - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive\n *\n * If the option is set to `true`, then the particular route can be matched without being\n * case sensitive\n *\n * @returns {Object} self\n *\n * @description\n * Adds a new route definition to the `$route` service.\n */\n this.when = function(path, route) {\n //copy original route object to preserve params inherited from proto chain\n var routeCopy = angular.copy(route);\n if (angular.isUndefined(routeCopy.reloadOnSearch)) {\n routeCopy.reloadOnSearch = true;\n }\n if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) {\n routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch;\n }\n routes[path] = angular.extend(\n routeCopy,\n path && pathRegExp(path, routeCopy)\n );\n\n // create redirection for trailing slashes\n if (path) {\n var redirectPath = (path[path.length - 1] == '/')\n ? path.substr(0, path.length - 1)\n : path + '/';\n\n routes[redirectPath] = angular.extend(\n {redirectTo: path},\n pathRegExp(redirectPath, routeCopy)\n );\n }\n\n return this;\n };\n\n /**\n * @ngdoc property\n * @name $routeProvider#caseInsensitiveMatch\n * @description\n *\n * A boolean property indicating if routes defined\n * using this provider should be matched using a case insensitive\n * algorithm. Defaults to `false`.\n */\n this.caseInsensitiveMatch = false;\n\n /**\n * @param path {string} path\n * @param opts {Object} options\n * @return {?Object}\n *\n * @description\n * Normalizes the given path, returning a regular expression\n * and the original path.\n *\n * Inspired by pathRexp in visionmedia/express/lib/utils.js.\n */\n function pathRegExp(path, opts) {\n var insensitive = opts.caseInsensitiveMatch,\n ret = {\n originalPath: path,\n regexp: path\n },\n keys = ret.keys = [];\n\n path = path\n .replace(/([().])/g, '\\\\$1')\n .replace(/(\\/)?:(\\w+)([\\?\\*])?/g, function(_, slash, key, option) {\n var optional = option === '?' ? option : null;\n var star = option === '*' ? option : null;\n keys.push({ name: key, optional: !!optional });\n slash = slash || '';\n return ''\n + (optional ? '' : slash)\n + '(?:'\n + (optional ? slash : '')\n + (star && '(.+?)' || '([^/]+)')\n + (optional || '')\n + ')'\n + (optional || '');\n })\n .replace(/([\\/$\\*])/g, '\\\\$1');\n\n ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : '');\n return ret;\n }\n\n /**\n * @ngdoc method\n * @name $routeProvider#otherwise\n *\n * @description\n * Sets route definition that will be used on route change when no other route definition\n * is matched.\n *\n * @param {Object|string} params Mapping information to be assigned to `$route.current`.\n * If called with a string, the value maps to `redirectTo`.\n * @returns {Object} self\n */\n this.otherwise = function(params) {\n if (typeof params === 'string') {\n params = {redirectTo: params};\n }\n this.when(null, params);\n return this;\n };\n\n\n this.$get = ['$rootScope',\n '$location',\n '$routeParams',\n '$q',\n '$injector',\n '$templateRequest',\n '$sce',\n function($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce) {\n\n /**\n * @ngdoc service\n * @name $route\n * @requires $location\n * @requires $routeParams\n *\n * @property {Object} current Reference to the current route definition.\n * The route definition contains:\n *\n * - `controller`: The controller constructor as define in route definition.\n * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for\n * controller instantiation. The `locals` contain\n * the resolved values of the `resolve` map. Additionally the `locals` also contain:\n *\n * - `$scope` - The current route scope.\n * - `$template` - The current route template HTML.\n *\n * @property {Object} routes Object with all route configuration Objects as its properties.\n *\n * @description\n * `$route` is used for deep-linking URLs to controllers and views (HTML partials).\n * It watches `$location.url()` and tries to map the path to an existing route definition.\n *\n * Requires the {@link ngRoute `ngRoute`} module to be installed.\n *\n * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API.\n *\n * The `$route` service is typically used in conjunction with the\n * {@link ngRoute.directive:ngView `ngView`} directive and the\n * {@link ngRoute.$routeParams `$routeParams`} service.\n *\n * @example\n * This example shows how changing the URL hash causes the `$route` to match a route against the\n * URL, and the `ngView` pulls in the partial.\n *\n * \n * \n *
\n * Choose:\n * Moby |\n * Moby: Ch1 |\n * Gatsby |\n * Gatsby: Ch4 |\n * Scarlet Letter
\n *\n *
\n *\n *
\n *\n *
$location.path() = {{$location.path()}}
\n *
$route.current.templateUrl = {{$route.current.templateUrl}}
\n *
$route.current.params = {{$route.current.params}}
\n *
$route.current.scope.name = {{$route.current.scope.name}}
\n *
$routeParams = {{$routeParams}}
\n *
\n *
\n *\n * \n * controller: {{name}}
\n * Book Id: {{params.bookId}}
\n *
\n *\n * \n * controller: {{name}}
\n * Book Id: {{params.bookId}}
\n * Chapter Id: {{params.chapterId}}\n *
\n *\n * \n * angular.module('ngRouteExample', ['ngRoute'])\n *\n * .controller('MainController', function($scope, $route, $routeParams, $location) {\n * $scope.$route = $route;\n * $scope.$location = $location;\n * $scope.$routeParams = $routeParams;\n * })\n *\n * .controller('BookController', function($scope, $routeParams) {\n * $scope.name = \"BookController\";\n * $scope.params = $routeParams;\n * })\n *\n * .controller('ChapterController', function($scope, $routeParams) {\n * $scope.name = \"ChapterController\";\n * $scope.params = $routeParams;\n * })\n *\n * .config(function($routeProvider, $locationProvider) {\n * $routeProvider\n * .when('/Book/:bookId', {\n * templateUrl: 'book.html',\n * controller: 'BookController',\n * resolve: {\n * // I will cause a 1 second delay\n * delay: function($q, $timeout) {\n * var delay = $q.defer();\n * $timeout(delay.resolve, 1000);\n * return delay.promise;\n * }\n * }\n * })\n * .when('/Book/:bookId/ch/:chapterId', {\n * templateUrl: 'chapter.html',\n * controller: 'ChapterController'\n * });\n *\n * // configure html5 to get links working on jsfiddle\n * $locationProvider.html5Mode(true);\n * });\n *\n * \n *\n * \n * it('should load and compile correct template', function() {\n * element(by.linkText('Moby: Ch1')).click();\n * var content = element(by.css('[ng-view]')).getText();\n * expect(content).toMatch(/controller\\: ChapterController/);\n * expect(content).toMatch(/Book Id\\: Moby/);\n * expect(content).toMatch(/Chapter Id\\: 1/);\n *\n * element(by.partialLinkText('Scarlet')).click();\n *\n * content = element(by.css('[ng-view]')).getText();\n * expect(content).toMatch(/controller\\: BookController/);\n * expect(content).toMatch(/Book Id\\: Scarlet/);\n * });\n * \n *
\n */\n\n /**\n * @ngdoc event\n * @name $route#$routeChangeStart\n * @eventType broadcast on root scope\n * @description\n * Broadcasted before a route change. At this point the route services starts\n * resolving all of the dependencies needed for the route change to occur.\n * Typically this involves fetching the view template as well as any dependencies\n * defined in `resolve` route property. Once all of the dependencies are resolved\n * `$routeChangeSuccess` is fired.\n *\n * The route change (and the `$location` change that triggered it) can be prevented\n * by calling `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on}\n * for more details about event object.\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {Route} next Future route information.\n * @param {Route} current Current route information.\n */\n\n /**\n * @ngdoc event\n * @name $route#$routeChangeSuccess\n * @eventType broadcast on root scope\n * @description\n * Broadcasted after a route dependencies are resolved.\n * {@link ngRoute.directive:ngView ngView} listens for the directive\n * to instantiate the controller and render the view.\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {Route} current Current route information.\n * @param {Route|Undefined} previous Previous route information, or undefined if current is\n * first route entered.\n */\n\n /**\n * @ngdoc event\n * @name $route#$routeChangeError\n * @eventType broadcast on root scope\n * @description\n * Broadcasted if any of the resolve promises are rejected.\n *\n * @param {Object} angularEvent Synthetic event object\n * @param {Route} current Current route information.\n * @param {Route} previous Previous route information.\n * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.\n */\n\n /**\n * @ngdoc event\n * @name $route#$routeUpdate\n * @eventType broadcast on root scope\n * @description\n *\n * The `reloadOnSearch` property has been set to false, and we are reusing the same\n * instance of the Controller.\n */\n\n var forceReload = false,\n preparedRoute,\n preparedRouteIsUpdateOnly,\n $route = {\n routes: routes,\n\n /**\n * @ngdoc method\n * @name $route#reload\n *\n * @description\n * Causes `$route` service to reload the current route even if\n * {@link ng.$location $location} hasn't changed.\n *\n * As a result of that, {@link ngRoute.directive:ngView ngView}\n * creates new scope and reinstantiates the controller.\n */\n reload: function() {\n forceReload = true;\n $rootScope.$evalAsync(function() {\n // Don't support cancellation of a reload for now...\n prepareRoute();\n commitRoute();\n });\n },\n\n /**\n * @ngdoc method\n * @name $route#updateParams\n *\n * @description\n * Causes `$route` service to update the current URL, replacing\n * current route parameters with those specified in `newParams`.\n * Provided property names that match the route's path segment\n * definitions will be interpolated into the location's path, while\n * remaining properties will be treated as query params.\n *\n * @param {Object} newParams mapping of URL parameter names to values\n */\n updateParams: function(newParams) {\n if (this.current && this.current.$$route) {\n var searchParams = {}, self=this;\n\n angular.forEach(Object.keys(newParams), function(key) {\n if (!self.current.pathParams[key]) searchParams[key] = newParams[key];\n });\n\n newParams = angular.extend({}, this.current.params, newParams);\n $location.path(interpolate(this.current.$$route.originalPath, newParams));\n $location.search(angular.extend({}, $location.search(), searchParams));\n }\n else {\n throw $routeMinErr('norout', 'Tried updating route when with no current route');\n }\n }\n };\n\n $rootScope.$on('$locationChangeStart', prepareRoute);\n $rootScope.$on('$locationChangeSuccess', commitRoute);\n\n return $route;\n\n /////////////////////////////////////////////////////\n\n /**\n * @param on {string} current url\n * @param route {Object} route regexp to match the url against\n * @return {?Object}\n *\n * @description\n * Check if the route matches the current url.\n *\n * Inspired by match in\n * visionmedia/express/lib/router/router.js.\n */\n function switchRouteMatcher(on, route) {\n var keys = route.keys,\n params = {};\n\n if (!route.regexp) return null;\n\n var m = route.regexp.exec(on);\n if (!m) return null;\n\n for (var i = 1, len = m.length; i < len; ++i) {\n var key = keys[i - 1];\n\n var val = m[i];\n\n if (key && val) {\n params[key.name] = val;\n }\n }\n return params;\n }\n\n function prepareRoute($locationEvent) {\n var lastRoute = $route.current;\n\n preparedRoute = parseRoute();\n preparedRouteIsUpdateOnly = preparedRoute && lastRoute && preparedRoute.$$route === lastRoute.$$route\n && angular.equals(preparedRoute.pathParams, lastRoute.pathParams)\n && !preparedRoute.reloadOnSearch && !forceReload;\n\n if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) {\n if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) {\n if ($locationEvent) {\n $locationEvent.preventDefault();\n }\n }\n }\n }\n\n function commitRoute() {\n var lastRoute = $route.current;\n var nextRoute = preparedRoute;\n\n if (preparedRouteIsUpdateOnly) {\n lastRoute.params = nextRoute.params;\n angular.copy(lastRoute.params, $routeParams);\n $rootScope.$broadcast('$routeUpdate', lastRoute);\n } else if (nextRoute || lastRoute) {\n forceReload = false;\n $route.current = nextRoute;\n if (nextRoute) {\n if (nextRoute.redirectTo) {\n if (angular.isString(nextRoute.redirectTo)) {\n $location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search(nextRoute.params)\n .replace();\n } else {\n $location.url(nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search()))\n .replace();\n }\n }\n }\n\n $q.when(nextRoute).\n then(function() {\n if (nextRoute) {\n var locals = angular.extend({}, nextRoute.resolve),\n template, templateUrl;\n\n angular.forEach(locals, function(value, key) {\n locals[key] = angular.isString(value) ?\n $injector.get(value) : $injector.invoke(value, null, null, key);\n });\n\n if (angular.isDefined(template = nextRoute.template)) {\n if (angular.isFunction(template)) {\n template = template(nextRoute.params);\n }\n } else if (angular.isDefined(templateUrl = nextRoute.templateUrl)) {\n if (angular.isFunction(templateUrl)) {\n templateUrl = templateUrl(nextRoute.params);\n }\n templateUrl = $sce.getTrustedResourceUrl(templateUrl);\n if (angular.isDefined(templateUrl)) {\n nextRoute.loadedTemplateUrl = templateUrl;\n template = $templateRequest(templateUrl);\n }\n }\n if (angular.isDefined(template)) {\n locals['$template'] = template;\n }\n return $q.all(locals);\n }\n }).\n // after route change\n then(function(locals) {\n if (nextRoute == $route.current) {\n if (nextRoute) {\n nextRoute.locals = locals;\n angular.copy(nextRoute.params, $routeParams);\n }\n $rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute);\n }\n }, function(error) {\n if (nextRoute == $route.current) {\n $rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error);\n }\n });\n }\n }\n\n\n /**\n * @returns {Object} the current active route, by matching it against the URL\n */\n function parseRoute() {\n // Match a route\n var params, match;\n angular.forEach(routes, function(route, path) {\n if (!match && (params = switchRouteMatcher($location.path(), route))) {\n match = inherit(route, {\n params: angular.extend({}, $location.search(), params),\n pathParams: params});\n match.$$route = route;\n }\n });\n // No route matched; fallback to \"otherwise\" route\n return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});\n }\n\n /**\n * @returns {string} interpolation of the redirect path with the parameters\n */\n function interpolate(string, params) {\n var result = [];\n angular.forEach((string || '').split(':'), function(segment, i) {\n if (i === 0) {\n result.push(segment);\n } else {\n var segmentMatch = segment.match(/(\\w+)(?:[?*])?(.*)/);\n var key = segmentMatch[1];\n result.push(params[key]);\n result.push(segmentMatch[2] || '');\n delete params[key];\n }\n });\n return result.join('');\n }\n }];\n}\n\nngRouteModule.provider('$routeParams', $RouteParamsProvider);\n\n\n/**\n * @ngdoc service\n * @name $routeParams\n * @requires $route\n *\n * @description\n * The `$routeParams` service allows you to retrieve the current set of route parameters.\n *\n * Requires the {@link ngRoute `ngRoute`} module to be installed.\n *\n * The route parameters are a combination of {@link ng.$location `$location`}'s\n * {@link ng.$location#search `search()`} and {@link ng.$location#path `path()`}.\n * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched.\n *\n * In case of parameter name collision, `path` params take precedence over `search` params.\n *\n * The service guarantees that the identity of the `$routeParams` object will remain unchanged\n * (but its properties will likely change) even when a route change occurs.\n *\n * Note that the `$routeParams` are only updated *after* a route change completes successfully.\n * This means that you cannot rely on `$routeParams` being correct in route resolve functions.\n * Instead you can use `$route.current.params` to access the new route's parameters.\n *\n * @example\n * ```js\n * // Given:\n * // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby\n * // Route: /Chapter/:chapterId/Section/:sectionId\n * //\n * // Then\n * $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}\n * ```\n */\nfunction $RouteParamsProvider() {\n this.$get = function() { return {}; };\n}\n\nngRouteModule.directive('ngView', ngViewFactory);\nngRouteModule.directive('ngView', ngViewFillContentFactory);\n\n\n/**\n * @ngdoc directive\n * @name ngView\n * @restrict ECA\n *\n * @description\n * # Overview\n * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by\n * including the rendered template of the current route into the main layout (`index.html`) file.\n * Every time the current route changes, the included view changes with it according to the\n * configuration of the `$route` service.\n *\n * Requires the {@link ngRoute `ngRoute`} module to be installed.\n *\n * @animations\n * enter - animation is used to bring new content into the browser.\n * leave - animation is used to animate existing content away.\n *\n * The enter and leave animation occur concurrently.\n *\n * @scope\n * @priority 400\n * @param {string=} onload Expression to evaluate whenever the view updates.\n *\n * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll\n * $anchorScroll} to scroll the viewport after the view is updated.\n *\n * - If the attribute is not set, disable scrolling.\n * - If the attribute is set without value, enable scrolling.\n * - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated\n * as an expression yields a truthy value.\n * @example\n \n \n
\n Choose:\n Moby |\n Moby: Ch1 |\n Gatsby |\n Gatsby: Ch4 |\n Scarlet Letter
\n\n
\n
\n
\n
\n\n
$location.path() = {{main.$location.path()}}
\n
$route.current.templateUrl = {{main.$route.current.templateUrl}}
\n
$route.current.params = {{main.$route.current.params}}
\n
$routeParams = {{main.$routeParams}}
\n
\n
\n\n \n
\n controller: {{book.name}}
\n Book Id: {{book.params.bookId}}
\n
\n
\n\n \n
\n controller: {{chapter.name}}
\n Book Id: {{chapter.params.bookId}}
\n Chapter Id: {{chapter.params.chapterId}}\n
\n
\n\n \n .view-animate-container {\n position:relative;\n height:100px!important;\n background:white;\n border:1px solid black;\n height:40px;\n overflow:hidden;\n }\n\n .view-animate {\n padding:10px;\n }\n\n .view-animate.ng-enter, .view-animate.ng-leave {\n -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;\n transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;\n\n display:block;\n width:100%;\n border-left:1px solid black;\n\n position:absolute;\n top:0;\n left:0;\n right:0;\n bottom:0;\n padding:10px;\n }\n\n .view-animate.ng-enter {\n left:100%;\n }\n .view-animate.ng-enter.ng-enter-active {\n left:0;\n }\n .view-animate.ng-leave.ng-leave-active {\n left:-100%;\n }\n \n\n \n angular.module('ngViewExample', ['ngRoute', 'ngAnimate'])\n .config(['$routeProvider', '$locationProvider',\n function($routeProvider, $locationProvider) {\n $routeProvider\n .when('/Book/:bookId', {\n templateUrl: 'book.html',\n controller: 'BookCtrl',\n controllerAs: 'book'\n })\n .when('/Book/:bookId/ch/:chapterId', {\n templateUrl: 'chapter.html',\n controller: 'ChapterCtrl',\n controllerAs: 'chapter'\n });\n\n $locationProvider.html5Mode(true);\n }])\n .controller('MainCtrl', ['$route', '$routeParams', '$location',\n function($route, $routeParams, $location) {\n this.$route = $route;\n this.$location = $location;\n this.$routeParams = $routeParams;\n }])\n .controller('BookCtrl', ['$routeParams', function($routeParams) {\n this.name = \"BookCtrl\";\n this.params = $routeParams;\n }])\n .controller('ChapterCtrl', ['$routeParams', function($routeParams) {\n this.name = \"ChapterCtrl\";\n this.params = $routeParams;\n }]);\n\n \n\n \n it('should load and compile correct template', function() {\n element(by.linkText('Moby: Ch1')).click();\n var content = element(by.css('[ng-view]')).getText();\n expect(content).toMatch(/controller\\: ChapterCtrl/);\n expect(content).toMatch(/Book Id\\: Moby/);\n expect(content).toMatch(/Chapter Id\\: 1/);\n\n element(by.partialLinkText('Scarlet')).click();\n\n content = element(by.css('[ng-view]')).getText();\n expect(content).toMatch(/controller\\: BookCtrl/);\n expect(content).toMatch(/Book Id\\: Scarlet/);\n });\n \n
\n */\n\n\n/**\n * @ngdoc event\n * @name ngView#$viewContentLoaded\n * @eventType emit on the current ngView scope\n * @description\n * Emitted every time the ngView content is reloaded.\n */\nngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];\nfunction ngViewFactory($route, $anchorScroll, $animate) {\n return {\n restrict: 'ECA',\n terminal: true,\n priority: 400,\n transclude: 'element',\n link: function(scope, $element, attr, ctrl, $transclude) {\n var currentScope,\n currentElement,\n previousLeaveAnimation,\n autoScrollExp = attr.autoscroll,\n onloadExp = attr.onload || '';\n\n scope.$on('$routeChangeSuccess', update);\n update();\n\n function cleanupLastView() {\n if (previousLeaveAnimation) {\n $animate.cancel(previousLeaveAnimation);\n previousLeaveAnimation = null;\n }\n\n if (currentScope) {\n currentScope.$destroy();\n currentScope = null;\n }\n if (currentElement) {\n previousLeaveAnimation = $animate.leave(currentElement);\n previousLeaveAnimation.then(function() {\n previousLeaveAnimation = null;\n });\n currentElement = null;\n }\n }\n\n function update() {\n var locals = $route.current && $route.current.locals,\n template = locals && locals.$template;\n\n if (angular.isDefined(template)) {\n var newScope = scope.$new();\n var current = $route.current;\n\n // Note: This will also link all children of ng-view that were contained in the original\n // html. If that content contains controllers, ... they could pollute/change the scope.\n // However, using ng-view on an element with additional content does not make sense...\n // Note: We can't remove them in the cloneAttchFn of $transclude as that\n // function is called before linking the content, which would apply child\n // directives to non existing elements.\n var clone = $transclude(newScope, function(clone) {\n $animate.enter(clone, null, currentElement || $element).then(function onNgViewEnter() {\n if (angular.isDefined(autoScrollExp)\n && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n $anchorScroll();\n }\n });\n cleanupLastView();\n });\n\n currentElement = clone;\n currentScope = current.scope = newScope;\n currentScope.$emit('$viewContentLoaded');\n currentScope.$eval(onloadExp);\n } else {\n cleanupLastView();\n }\n }\n }\n };\n}\n\n// This directive is called during the $transclude call of the first `ngView` directive.\n// It will replace and compile the content of the element with the loaded template.\n// We need this directive so that the element content is already filled when\n// the link function of another directive on the same element as ngView\n// is called.\nngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];\nfunction ngViewFillContentFactory($compile, $controller, $route) {\n return {\n restrict: 'ECA',\n priority: -400,\n link: function(scope, $element) {\n var current = $route.current,\n locals = current.locals;\n\n $element.html(locals.$template);\n\n var link = $compile($element.contents());\n\n if (current.controller) {\n locals.$scope = scope;\n var controller = $controller(current.controller, locals);\n if (current.controllerAs) {\n scope[current.controllerAs] = controller;\n }\n $element.data('$ngControllerController', controller);\n $element.children().data('$ngControllerController', controller);\n }\n\n link(scope);\n }\n };\n}\n\n\n})(window, window.angular);\n", - "/**\n * @license AngularJS v1.3.11\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {'use strict';\n\nvar $sanitizeMinErr = angular.$$minErr('$sanitize');\n\n/**\n * @ngdoc module\n * @name ngSanitize\n * @description\n *\n * # ngSanitize\n *\n * The `ngSanitize` module provides functionality to sanitize HTML.\n *\n *\n *
\n *\n * See {@link ngSanitize.$sanitize `$sanitize`} for usage.\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on: HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n * start: function(tag, attrs, unary) {},\n * end: function(tag) {},\n * chars: function(text) {},\n * comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name $sanitize\n * @kind function\n *\n * @description\n * The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are\n * then serialized back to properly escaped html string. This means that no unsafe input can make\n * it into the returned string, however, since our parser is more strict than a typical browser\n * parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n * browser, won't make it through the sanitizer. The input may also contain SVG markup.\n * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and\n * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.\n *\n * @param {string} html HTML input.\n * @returns {string} Sanitized HTML.\n *\n * @example\n \n \n \n
\n Snippet: \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
DirectiveHowSourceRendered
ng-bind-htmlAutomatically uses $sanitize
<div ng-bind-html=\"snippet\">
</div>
ng-bind-htmlBypass $sanitize by explicitly trusting the dangerous value\n
<div ng-bind-html=\"deliberatelyTrustDangerousSnippet()\">\n</div>
\n
ng-bindAutomatically escapes
<div ng-bind=\"snippet\">
</div>
\n
\n
\n \n it('should sanitize the html snippet by default', function() {\n expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).\n toBe('

an html\\nclick here\\nsnippet

');\n });\n\n it('should inline raw snippet if bound to a trusted value', function() {\n expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).\n toBe(\"

an html\\n\" +\n \"click here\\n\" +\n \"snippet

\");\n });\n\n it('should escape snippet without any filter', function() {\n expect(element(by.css('#bind-default div')).getInnerHtml()).\n toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n \"snippet</p>\");\n });\n\n it('should update', function() {\n element(by.model('snippet')).clear();\n element(by.model('snippet')).sendKeys('new text');\n expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).\n toBe('new text');\n expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe(\n 'new text');\n expect(element(by.css('#bind-default div')).getInnerHtml()).toBe(\n \"new <b onclick=\\\"alert(1)\\\">text</b>\");\n });\n
\n
\n */\nfunction $SanitizeProvider() {\n this.$get = ['$$sanitizeUri', function($$sanitizeUri) {\n return function(html) {\n var buf = [];\n htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {\n return !/^unsafe/.test($$sanitizeUri(uri, isImage));\n }));\n return buf.join('');\n };\n }];\n}\n\nfunction sanitizeText(chars) {\n var buf = [];\n var writer = htmlSanitizeWriter(buf, angular.noop);\n writer.chars(chars);\n return buf.join('');\n}\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP =\n /^<((?:[a-zA-Z])[\\w:-]*)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*(>?)/,\n END_TAG_REGEXP = /^<\\/\\s*([\\w:-]+)[^>]*>/,\n ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n BEGIN_TAG_REGEXP = /^/g,\n DOCTYPE_REGEXP = /]*?)>/i,\n CDATA_REGEXP = //g,\n SURROGATE_PAIR_REGEXP = /[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/g,\n // Match everything outside of normal chars and \" (quote character)\n NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g;\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n optionalEndTagElements = angular.extend({},\n optionalEndTagInlineElements,\n optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,\" +\n \"aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,\" +\n \"h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,\" +\n \"bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,\" +\n \"samp,small,span,strike,strong,sub,sup,time,tt,u,var\"));\n\n// SVG Elements\n// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements\nvar svgElements = makeMap(\"animate,animateColor,animateMotion,animateTransform,circle,defs,\" +\n \"desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,\" +\n \"line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set,\" +\n \"stop,svg,switch,text,title,tspan,use\");\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({},\n voidElements,\n blockElements,\n inlineElements,\n optionalEndTagElements,\n svgElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap,xlink:href\");\n\nvar htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' +\n 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' +\n 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' +\n 'scope,scrolling,shape,size,span,start,summary,target,title,type,' +\n 'valign,value,vspace,width');\n\n// SVG attributes (without \"id\" and \"name\" attributes)\n// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes\nvar svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +\n 'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,' +\n 'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,' +\n 'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,' +\n 'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,' +\n 'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,' +\n 'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,' +\n 'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,' +\n 'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,' +\n 'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,' +\n 'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,' +\n 'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,' +\n 'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,' +\n 'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,' +\n 'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,' +\n 'zoomAndPan');\n\nvar validAttrs = angular.extend({},\n uriAttrs,\n svgAttrs,\n htmlAttrs);\n\nfunction makeMap(str) {\n var obj = {}, items = str.split(','), i;\n for (i = 0; i < items.length; i++) obj[items[i]] = true;\n return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n * start: function(tag, attrs, unary) {},\n * end: function(tag) {},\n * chars: function(text) {},\n * comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser(html, handler) {\n if (typeof html !== 'string') {\n if (html === null || typeof html === 'undefined') {\n html = '';\n } else {\n html = '' + html;\n }\n }\n var index, chars, match, stack = [], last = html, text;\n stack.last = function() { return stack[ stack.length - 1 ]; };\n\n while (html) {\n text = '';\n chars = true;\n\n // Make sure we're not in a script or style element\n if (!stack.last() || !specialElements[ stack.last() ]) {\n\n // Comment\n if (html.indexOf(\"\", index) === index) {\n if (handler.comment) handler.comment(html.substring(4, index));\n html = html.substring(index + 3);\n chars = false;\n }\n // DOCTYPE\n } else if (DOCTYPE_REGEXP.test(html)) {\n match = html.match(DOCTYPE_REGEXP);\n\n if (match) {\n html = html.replace(match[0], '');\n chars = false;\n }\n // end tag\n } else if (BEGING_END_TAGE_REGEXP.test(html)) {\n match = html.match(END_TAG_REGEXP);\n\n if (match) {\n html = html.substring(match[0].length);\n match[0].replace(END_TAG_REGEXP, parseEndTag);\n chars = false;\n }\n\n // start tag\n } else if (BEGIN_TAG_REGEXP.test(html)) {\n match = html.match(START_TAG_REGEXP);\n\n if (match) {\n // We only have a valid start-tag if there is a '>'.\n if (match[4]) {\n html = html.substring(match[0].length);\n match[0].replace(START_TAG_REGEXP, parseStartTag);\n }\n chars = false;\n } else {\n // no ending tag found --- this piece should be encoded as an entity.\n text += '<';\n html = html.substring(1);\n }\n }\n\n if (chars) {\n index = html.indexOf(\"<\");\n\n text += index < 0 ? html : html.substring(0, index);\n html = index < 0 ? \"\" : html.substring(index);\n\n if (handler.chars) handler.chars(decodeEntities(text));\n }\n\n } else {\n html = html.replace(new RegExp(\"(.*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'),\n function(all, text) {\n text = text.replace(COMMENT_REGEXP, \"$1\").replace(CDATA_REGEXP, \"$1\");\n\n if (handler.chars) handler.chars(decodeEntities(text));\n\n return \"\";\n });\n\n parseEndTag(\"\", stack.last());\n }\n\n if (html == last) {\n throw $sanitizeMinErr('badparse', \"The sanitizer was unable to parse the following block \" +\n \"of html: {0}\", html);\n }\n last = html;\n }\n\n // Clean up any remaining tags\n parseEndTag();\n\n function parseStartTag(tag, tagName, rest, unary) {\n tagName = angular.lowercase(tagName);\n if (blockElements[ tagName ]) {\n while (stack.last() && inlineElements[ stack.last() ]) {\n parseEndTag(\"\", stack.last());\n }\n }\n\n if (optionalEndTagElements[ tagName ] && stack.last() == tagName) {\n parseEndTag(\"\", tagName);\n }\n\n unary = voidElements[ tagName ] || !!unary;\n\n if (!unary)\n stack.push(tagName);\n\n var attrs = {};\n\n rest.replace(ATTR_REGEXP,\n function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) {\n var value = doubleQuotedValue\n || singleQuotedValue\n || unquotedValue\n || '';\n\n attrs[name] = decodeEntities(value);\n });\n if (handler.start) handler.start(tagName, attrs, unary);\n }\n\n function parseEndTag(tag, tagName) {\n var pos = 0, i;\n tagName = angular.lowercase(tagName);\n if (tagName)\n // Find the closest opened tag of the same type\n for (pos = stack.length - 1; pos >= 0; pos--)\n if (stack[ pos ] == tagName)\n break;\n\n if (pos >= 0) {\n // Close all the open elements, up the stack\n for (i = stack.length - 1; i >= pos; i--)\n if (handler.end) handler.end(stack[ i ]);\n\n // Remove the open elements from the stack\n stack.length = pos;\n }\n }\n}\n\nvar hiddenPre=document.createElement(\"pre\");\nvar spaceRe = /^(\\s*)([\\s\\S]*?)(\\s*)$/;\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nfunction decodeEntities(value) {\n if (!value) { return ''; }\n\n // Note: IE8 does not preserve spaces at the start/end of innerHTML\n // so we must capture them and reattach them afterward\n var parts = spaceRe.exec(value);\n var spaceBefore = parts[1];\n var spaceAfter = parts[3];\n var content = parts[2];\n if (content) {\n hiddenPre.innerHTML=content.replace(//g, '>');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n * start: function(tag, attrs, unary) {},\n * end: function(tag) {},\n * chars: function(text) {},\n * comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf, uriValidator) {\n var ignore = false;\n var out = angular.bind(buf, buf.push);\n return {\n start: function(tag, attrs, unary) {\n tag = angular.lowercase(tag);\n if (!ignore && specialElements[tag]) {\n ignore = tag;\n }\n if (!ignore && validElements[tag] === true) {\n out('<');\n out(tag);\n angular.forEach(attrs, function(value, key) {\n var lkey=angular.lowercase(key);\n var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');\n if (validAttrs[lkey] === true &&\n (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {\n out(' ');\n out(key);\n out('=\"');\n out(encodeEntities(value));\n out('\"');\n }\n });\n out(unary ? '/>' : '>');\n }\n },\n end: function(tag) {\n tag = angular.lowercase(tag);\n if (!ignore && validElements[tag] === true) {\n out('');\n }\n if (tag == ignore) {\n ignore = false;\n }\n },\n chars: function(chars) {\n if (!ignore) {\n out(encodeEntities(chars));\n }\n }\n };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);\n\n/* global sanitizeText: false */\n\n/**\n * @ngdoc filter\n * @name linky\n * @kind function\n *\n * @description\n * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n * plain email address links.\n *\n * Requires the {@link ngSanitize `ngSanitize`} module to be installed.\n *\n * @param {string} text Input text.\n * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.\n * @returns {string} Html-linkified text.\n *\n * @usage\n \n *\n * @example\n \n \n \n
\n Snippet: \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
FilterSourceRendered
linky filter\n
<div ng-bind-html=\"snippet | linky\">
</div>
\n
\n
\n
linky target\n
<div ng-bind-html=\"snippetWithTarget | linky:'_blank'\">
</div>
\n
\n
\n
no filter
<div ng-bind=\"snippet\">
</div>
\n \n \n it('should linkify the snippet with urls', function() {\n expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).\n toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' +\n 'another@somewhere.org, and one more: ftp://127.0.0.1/.');\n expect(element.all(by.css('#linky-filter a')).count()).toEqual(4);\n });\n\n it('should not linkify snippet without the linky filter', function() {\n expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()).\n toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' +\n 'another@somewhere.org, and one more: ftp://127.0.0.1/.');\n expect(element.all(by.css('#escaped-html a')).count()).toEqual(0);\n });\n\n it('should update', function() {\n element(by.model('snippet')).clear();\n element(by.model('snippet')).sendKeys('new http://link.');\n expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).\n toBe('new http://link.');\n expect(element.all(by.css('#linky-filter a')).count()).toEqual(1);\n expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText())\n .toBe('new http://link.');\n });\n\n it('should work with the target property', function() {\n expect(element(by.id('linky-target')).\n element(by.binding(\"snippetWithTarget | linky:'_blank'\")).getText()).\n toBe('http://angularjs.org/');\n expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank');\n });\n \n \n */\nangular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {\n var LINKY_URL_REGEXP =\n /((ftp|https?):\\/\\/|(www\\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s.;,(){}<>\"”’]/,\n MAILTO_REGEXP = /^mailto:/;\n\n return function(text, target) {\n if (!text) return text;\n var match;\n var raw = text;\n var html = [];\n var url;\n var i;\n while ((match = raw.match(LINKY_URL_REGEXP))) {\n // We can not end in these as they are sometimes found at the end of the sentence\n url = match[0];\n // if we did not match ftp/http/www/mailto then assume mailto\n if (!match[2] && !match[4]) {\n url = (match[3] ? 'http://' : 'mailto:') + url;\n }\n i = match.index;\n addText(raw.substr(0, i));\n addLink(url, match[0].replace(MAILTO_REGEXP, ''));\n raw = raw.substring(i + match[0].length);\n }\n addText(raw);\n return $sanitize(html.join(''));\n\n function addText(text) {\n if (!text) {\n return;\n }\n html.push(sanitizeText(text));\n }\n\n function addLink(url, text) {\n html.push('');\n addText(text);\n html.push('');\n }\n };\n}]);\n\n\n})(window, window.angular);\n", - "/**\n * @license AngularJS v1.3.11\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {'use strict';\n\n/**\n * @ngdoc module\n * @name ngTouch\n * @description\n *\n * # ngTouch\n *\n * The `ngTouch` module provides touch events and other helpers for touch-enabled devices.\n * The implementation is based on jQuery Mobile touch event handling\n * ([jquerymobile.com](http://jquerymobile.com/)).\n *\n *\n * See {@link ngTouch.$swipe `$swipe`} for usage.\n *\n *
\n *\n */\n\n// define ngTouch module\n/* global -ngTouch */\nvar ngTouch = angular.module('ngTouch', []);\n\n/* global ngTouch: false */\n\n /**\n * @ngdoc service\n * @name $swipe\n *\n * @description\n * The `$swipe` service is a service that abstracts the messier details of hold-and-drag swipe\n * behavior, to make implementing swipe-related directives more convenient.\n *\n * Requires the {@link ngTouch `ngTouch`} module to be installed.\n *\n * `$swipe` is used by the `ngSwipeLeft` and `ngSwipeRight` directives in `ngTouch`, and by\n * `ngCarousel` in a separate component.\n *\n * # Usage\n * The `$swipe` service is an object with a single method: `bind`. `bind` takes an element\n * which is to be watched for swipes, and an object with four handler functions. See the\n * documentation for `bind` below.\n */\n\nngTouch.factory('$swipe', [function() {\n // The total distance in any direction before we make the call on swipe vs. scroll.\n var MOVE_BUFFER_RADIUS = 10;\n\n var POINTER_EVENTS = {\n 'mouse': {\n start: 'mousedown',\n move: 'mousemove',\n end: 'mouseup'\n },\n 'touch': {\n start: 'touchstart',\n move: 'touchmove',\n end: 'touchend',\n cancel: 'touchcancel'\n }\n };\n\n function getCoordinates(event) {\n var touches = event.touches && event.touches.length ? event.touches : [event];\n var e = (event.changedTouches && event.changedTouches[0]) ||\n (event.originalEvent && event.originalEvent.changedTouches &&\n event.originalEvent.changedTouches[0]) ||\n touches[0].originalEvent || touches[0];\n\n return {\n x: e.clientX,\n y: e.clientY\n };\n }\n\n function getEvents(pointerTypes, eventType) {\n var res = [];\n angular.forEach(pointerTypes, function(pointerType) {\n var eventName = POINTER_EVENTS[pointerType][eventType];\n if (eventName) {\n res.push(eventName);\n }\n });\n return res.join(' ');\n }\n\n return {\n /**\n * @ngdoc method\n * @name $swipe#bind\n *\n * @description\n * The main method of `$swipe`. It takes an element to be watched for swipe motions, and an\n * object containing event handlers.\n * The pointer types that should be used can be specified via the optional\n * third argument, which is an array of strings `'mouse'` and `'touch'`. By default,\n * `$swipe` will listen for `mouse` and `touch` events.\n *\n * The four events are `start`, `move`, `end`, and `cancel`. `start`, `move`, and `end`\n * receive as a parameter a coordinates object of the form `{ x: 150, y: 310 }`.\n *\n * `start` is called on either `mousedown` or `touchstart`. After this event, `$swipe` is\n * watching for `touchmove` or `mousemove` events. These events are ignored until the total\n * distance moved in either dimension exceeds a small threshold.\n *\n * Once this threshold is exceeded, either the horizontal or vertical delta is greater.\n * - If the horizontal distance is greater, this is a swipe and `move` and `end` events follow.\n * - If the vertical distance is greater, this is a scroll, and we let the browser take over.\n * A `cancel` event is sent.\n *\n * `move` is called on `mousemove` and `touchmove` after the above logic has determined that\n * a swipe is in progress.\n *\n * `end` is called when a swipe is successfully completed with a `touchend` or `mouseup`.\n *\n * `cancel` is called either on a `touchcancel` from the browser, or when we begin scrolling\n * as described above.\n *\n */\n bind: function(element, eventHandlers, pointerTypes) {\n // Absolute total movement, used to control swipe vs. scroll.\n var totalX, totalY;\n // Coordinates of the start position.\n var startCoords;\n // Last event's position.\n var lastPos;\n // Whether a swipe is active.\n var active = false;\n\n pointerTypes = pointerTypes || ['mouse', 'touch'];\n element.on(getEvents(pointerTypes, 'start'), function(event) {\n startCoords = getCoordinates(event);\n active = true;\n totalX = 0;\n totalY = 0;\n lastPos = startCoords;\n eventHandlers['start'] && eventHandlers['start'](startCoords, event);\n });\n var events = getEvents(pointerTypes, 'cancel');\n if (events) {\n element.on(events, function(event) {\n active = false;\n eventHandlers['cancel'] && eventHandlers['cancel'](event);\n });\n }\n\n element.on(getEvents(pointerTypes, 'move'), function(event) {\n if (!active) return;\n\n // Android will send a touchcancel if it thinks we're starting to scroll.\n // So when the total distance (+ or - or both) exceeds 10px in either direction,\n // we either:\n // - On totalX > totalY, we send preventDefault() and treat this as a swipe.\n // - On totalY > totalX, we let the browser handle it as a scroll.\n\n if (!startCoords) return;\n var coords = getCoordinates(event);\n\n totalX += Math.abs(coords.x - lastPos.x);\n totalY += Math.abs(coords.y - lastPos.y);\n\n lastPos = coords;\n\n if (totalX < MOVE_BUFFER_RADIUS && totalY < MOVE_BUFFER_RADIUS) {\n return;\n }\n\n // One of totalX or totalY has exceeded the buffer, so decide on swipe vs. scroll.\n if (totalY > totalX) {\n // Allow native scrolling to take over.\n active = false;\n eventHandlers['cancel'] && eventHandlers['cancel'](event);\n return;\n } else {\n // Prevent the browser from scrolling.\n event.preventDefault();\n eventHandlers['move'] && eventHandlers['move'](coords, event);\n }\n });\n\n element.on(getEvents(pointerTypes, 'end'), function(event) {\n if (!active) return;\n active = false;\n eventHandlers['end'] && eventHandlers['end'](getCoordinates(event), event);\n });\n }\n };\n}]);\n\n/* global ngTouch: false */\n\n/**\n * @ngdoc directive\n * @name ngClick\n *\n * @description\n * A more powerful replacement for the default ngClick designed to be used on touchscreen\n * devices. Most mobile browsers wait about 300ms after a tap-and-release before sending\n * the click event. This version handles them immediately, and then prevents the\n * following click event from propagating.\n *\n * Requires the {@link ngTouch `ngTouch`} module to be installed.\n *\n * This directive can fall back to using an ordinary click event, and so works on desktop\n * browsers as well as mobile.\n *\n * This directive also sets the CSS class `ng-click-active` while the element is being held\n * down (by a mouse click or touch) so you can restyle the depressed element if you wish.\n *\n * @element ANY\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate\n * upon tap. (Event object is available as `$event`)\n *\n * @example\n \n \n \n count: {{ count }}\n \n \n angular.module('ngClickExample', ['ngTouch']);\n \n \n */\n\nngTouch.config(['$provide', function($provide) {\n $provide.decorator('ngClickDirective', ['$delegate', function($delegate) {\n // drop the default ngClick directive\n $delegate.shift();\n return $delegate;\n }]);\n}]);\n\nngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement',\n function($parse, $timeout, $rootElement) {\n var TAP_DURATION = 750; // Shorter than 750ms is a tap, longer is a taphold or drag.\n var MOVE_TOLERANCE = 12; // 12px seems to work in most mobile browsers.\n var PREVENT_DURATION = 2500; // 2.5 seconds maximum from preventGhostClick call to click\n var CLICKBUSTER_THRESHOLD = 25; // 25 pixels in any dimension is the limit for busting clicks.\n\n var ACTIVE_CLASS_NAME = 'ng-click-active';\n var lastPreventedTime;\n var touchCoordinates;\n var lastLabelClickCoordinates;\n\n\n // TAP EVENTS AND GHOST CLICKS\n //\n // Why tap events?\n // Mobile browsers detect a tap, then wait a moment (usually ~300ms) to see if you're\n // double-tapping, and then fire a click event.\n //\n // This delay sucks and makes mobile apps feel unresponsive.\n // So we detect touchstart, touchmove, touchcancel and touchend ourselves and determine when\n // the user has tapped on something.\n //\n // What happens when the browser then generates a click event?\n // The browser, of course, also detects the tap and fires a click after a delay. This results in\n // tapping/clicking twice. We do \"clickbusting\" to prevent it.\n //\n // How does it work?\n // We attach global touchstart and click handlers, that run during the capture (early) phase.\n // So the sequence for a tap is:\n // - global touchstart: Sets an \"allowable region\" at the point touched.\n // - element's touchstart: Starts a touch\n // (- touchmove or touchcancel ends the touch, no click follows)\n // - element's touchend: Determines if the tap is valid (didn't move too far away, didn't hold\n // too long) and fires the user's tap handler. The touchend also calls preventGhostClick().\n // - preventGhostClick() removes the allowable region the global touchstart created.\n // - The browser generates a click event.\n // - The global click handler catches the click, and checks whether it was in an allowable region.\n // - If preventGhostClick was called, the region will have been removed, the click is busted.\n // - If the region is still there, the click proceeds normally. Therefore clicks on links and\n // other elements without ngTap on them work normally.\n //\n // This is an ugly, terrible hack!\n // Yeah, tell me about it. The alternatives are using the slow click events, or making our users\n // deal with the ghost clicks, so I consider this the least of evils. Fortunately Angular\n // encapsulates this ugly logic away from the user.\n //\n // Why not just put click handlers on the element?\n // We do that too, just to be sure. If the tap event caused the DOM to change,\n // it is possible another element is now in that position. To take account for these possibly\n // distinct elements, the handlers are global and care only about coordinates.\n\n // Checks if the coordinates are close enough to be within the region.\n function hit(x1, y1, x2, y2) {\n return Math.abs(x1 - x2) < CLICKBUSTER_THRESHOLD && Math.abs(y1 - y2) < CLICKBUSTER_THRESHOLD;\n }\n\n // Checks a list of allowable regions against a click location.\n // Returns true if the click should be allowed.\n // Splices out the allowable region from the list after it has been used.\n function checkAllowableRegions(touchCoordinates, x, y) {\n for (var i = 0; i < touchCoordinates.length; i += 2) {\n if (hit(touchCoordinates[i], touchCoordinates[i + 1], x, y)) {\n touchCoordinates.splice(i, i + 2);\n return true; // allowable region\n }\n }\n return false; // No allowable region; bust it.\n }\n\n // Global click handler that prevents the click if it's in a bustable zone and preventGhostClick\n // was called recently.\n function onClick(event) {\n if (Date.now() - lastPreventedTime > PREVENT_DURATION) {\n return; // Too old.\n }\n\n var touches = event.touches && event.touches.length ? event.touches : [event];\n var x = touches[0].clientX;\n var y = touches[0].clientY;\n // Work around desktop Webkit quirk where clicking a label will fire two clicks (on the label\n // and on the input element). Depending on the exact browser, this second click we don't want\n // to bust has either (0,0), negative coordinates, or coordinates equal to triggering label\n // click event\n if (x < 1 && y < 1) {\n return; // offscreen\n }\n if (lastLabelClickCoordinates &&\n lastLabelClickCoordinates[0] === x && lastLabelClickCoordinates[1] === y) {\n return; // input click triggered by label click\n }\n // reset label click coordinates on first subsequent click\n if (lastLabelClickCoordinates) {\n lastLabelClickCoordinates = null;\n }\n // remember label click coordinates to prevent click busting of trigger click event on input\n if (event.target.tagName.toLowerCase() === 'label') {\n lastLabelClickCoordinates = [x, y];\n }\n\n // Look for an allowable region containing this click.\n // If we find one, that means it was created by touchstart and not removed by\n // preventGhostClick, so we don't bust it.\n if (checkAllowableRegions(touchCoordinates, x, y)) {\n return;\n }\n\n // If we didn't find an allowable region, bust the click.\n event.stopPropagation();\n event.preventDefault();\n\n // Blur focused form elements\n event.target && event.target.blur();\n }\n\n\n // Global touchstart handler that creates an allowable region for a click event.\n // This allowable region can be removed by preventGhostClick if we want to bust it.\n function onTouchStart(event) {\n var touches = event.touches && event.touches.length ? event.touches : [event];\n var x = touches[0].clientX;\n var y = touches[0].clientY;\n touchCoordinates.push(x, y);\n\n $timeout(function() {\n // Remove the allowable region.\n for (var i = 0; i < touchCoordinates.length; i += 2) {\n if (touchCoordinates[i] == x && touchCoordinates[i + 1] == y) {\n touchCoordinates.splice(i, i + 2);\n return;\n }\n }\n }, PREVENT_DURATION, false);\n }\n\n // On the first call, attaches some event handlers. Then whenever it gets called, it creates a\n // zone around the touchstart where clicks will get busted.\n function preventGhostClick(x, y) {\n if (!touchCoordinates) {\n $rootElement[0].addEventListener('click', onClick, true);\n $rootElement[0].addEventListener('touchstart', onTouchStart, true);\n touchCoordinates = [];\n }\n\n lastPreventedTime = Date.now();\n\n checkAllowableRegions(touchCoordinates, x, y);\n }\n\n // Actual linking function.\n return function(scope, element, attr) {\n var clickHandler = $parse(attr.ngClick),\n tapping = false,\n tapElement, // Used to blur the element after a tap.\n startTime, // Used to check if the tap was held too long.\n touchStartX,\n touchStartY;\n\n function resetState() {\n tapping = false;\n element.removeClass(ACTIVE_CLASS_NAME);\n }\n\n element.on('touchstart', function(event) {\n tapping = true;\n tapElement = event.target ? event.target : event.srcElement; // IE uses srcElement.\n // Hack for Safari, which can target text nodes instead of containers.\n if (tapElement.nodeType == 3) {\n tapElement = tapElement.parentNode;\n }\n\n element.addClass(ACTIVE_CLASS_NAME);\n\n startTime = Date.now();\n\n var touches = event.touches && event.touches.length ? event.touches : [event];\n var e = touches[0].originalEvent || touches[0];\n touchStartX = e.clientX;\n touchStartY = e.clientY;\n });\n\n element.on('touchmove', function(event) {\n resetState();\n });\n\n element.on('touchcancel', function(event) {\n resetState();\n });\n\n element.on('touchend', function(event) {\n var diff = Date.now() - startTime;\n\n var touches = (event.changedTouches && event.changedTouches.length) ? event.changedTouches :\n ((event.touches && event.touches.length) ? event.touches : [event]);\n var e = touches[0].originalEvent || touches[0];\n var x = e.clientX;\n var y = e.clientY;\n var dist = Math.sqrt(Math.pow(x - touchStartX, 2) + Math.pow(y - touchStartY, 2));\n\n if (tapping && diff < TAP_DURATION && dist < MOVE_TOLERANCE) {\n // Call preventGhostClick so the clickbuster will catch the corresponding click.\n preventGhostClick(x, y);\n\n // Blur the focused element (the button, probably) before firing the callback.\n // This doesn't work perfectly on Android Chrome, but seems to work elsewhere.\n // I couldn't get anything to work reliably on Android Chrome.\n if (tapElement) {\n tapElement.blur();\n }\n\n if (!angular.isDefined(attr.disabled) || attr.disabled === false) {\n element.triggerHandler('click', [event]);\n }\n }\n\n resetState();\n });\n\n // Hack for iOS Safari's benefit. It goes searching for onclick handlers and is liable to click\n // something else nearby.\n element.onclick = function(event) { };\n\n // Actual click handler.\n // There are three different kinds of clicks, only two of which reach this point.\n // - On desktop browsers without touch events, their clicks will always come here.\n // - On mobile browsers, the simulated \"fast\" click will call this.\n // - But the browser's follow-up slow click will be \"busted\" before it reaches this handler.\n // Therefore it's safe to use this directive on both mobile and desktop.\n element.on('click', function(event, touchend) {\n scope.$apply(function() {\n clickHandler(scope, {$event: (touchend || event)});\n });\n });\n\n element.on('mousedown', function(event) {\n element.addClass(ACTIVE_CLASS_NAME);\n });\n\n element.on('mousemove mouseup', function(event) {\n element.removeClass(ACTIVE_CLASS_NAME);\n });\n\n };\n}]);\n\n/* global ngTouch: false */\n\n/**\n * @ngdoc directive\n * @name ngSwipeLeft\n *\n * @description\n * Specify custom behavior when an element is swiped to the left on a touchscreen device.\n * A leftward swipe is a quick, right-to-left slide of the finger.\n * Though ngSwipeLeft is designed for touch-based devices, it will work with a mouse click and drag\n * too.\n *\n * To disable the mouse click and drag functionality, add `ng-swipe-disable-mouse` to\n * the `ng-swipe-left` or `ng-swipe-right` DOM Element.\n *\n * Requires the {@link ngTouch `ngTouch`} module to be installed.\n *\n * @element ANY\n * @param {expression} ngSwipeLeft {@link guide/expression Expression} to evaluate\n * upon left swipe. (Event object is available as `$event`)\n *\n * @example\n \n \n
\n Some list content, like an email in the inbox\n
\n
\n \n \n
\n
\n \n angular.module('ngSwipeLeftExample', ['ngTouch']);\n \n
\n */\n\n/**\n * @ngdoc directive\n * @name ngSwipeRight\n *\n * @description\n * Specify custom behavior when an element is swiped to the right on a touchscreen device.\n * A rightward swipe is a quick, left-to-right slide of the finger.\n * Though ngSwipeRight is designed for touch-based devices, it will work with a mouse click and drag\n * too.\n *\n * Requires the {@link ngTouch `ngTouch`} module to be installed.\n *\n * @element ANY\n * @param {expression} ngSwipeRight {@link guide/expression Expression} to evaluate\n * upon right swipe. (Event object is available as `$event`)\n *\n * @example\n \n \n
\n Some list content, like an email in the inbox\n
\n
\n \n \n
\n
\n \n angular.module('ngSwipeRightExample', ['ngTouch']);\n \n
\n */\n\nfunction makeSwipeDirective(directiveName, direction, eventName) {\n ngTouch.directive(directiveName, ['$parse', '$swipe', function($parse, $swipe) {\n // The maximum vertical delta for a swipe should be less than 75px.\n var MAX_VERTICAL_DISTANCE = 75;\n // Vertical distance should not be more than a fraction of the horizontal distance.\n var MAX_VERTICAL_RATIO = 0.3;\n // At least a 30px lateral motion is necessary for a swipe.\n var MIN_HORIZONTAL_DISTANCE = 30;\n\n return function(scope, element, attr) {\n var swipeHandler = $parse(attr[directiveName]);\n\n var startCoords, valid;\n\n function validSwipe(coords) {\n // Check that it's within the coordinates.\n // Absolute vertical distance must be within tolerances.\n // Horizontal distance, we take the current X - the starting X.\n // This is negative for leftward swipes and positive for rightward swipes.\n // After multiplying by the direction (-1 for left, +1 for right), legal swipes\n // (ie. same direction as the directive wants) will have a positive delta and\n // illegal ones a negative delta.\n // Therefore this delta must be positive, and larger than the minimum.\n if (!startCoords) return false;\n var deltaY = Math.abs(coords.y - startCoords.y);\n var deltaX = (coords.x - startCoords.x) * direction;\n return valid && // Short circuit for already-invalidated swipes.\n deltaY < MAX_VERTICAL_DISTANCE &&\n deltaX > 0 &&\n deltaX > MIN_HORIZONTAL_DISTANCE &&\n deltaY / deltaX < MAX_VERTICAL_RATIO;\n }\n\n var pointerTypes = ['touch'];\n if (!angular.isDefined(attr['ngSwipeDisableMouse'])) {\n pointerTypes.push('mouse');\n }\n $swipe.bind(element, {\n 'start': function(coords, event) {\n startCoords = coords;\n valid = true;\n },\n 'cancel': function(event) {\n valid = false;\n },\n 'end': function(coords, event) {\n if (validSwipe(coords)) {\n scope.$apply(function() {\n element.triggerHandler(eventName);\n swipeHandler(scope, {$event: event});\n });\n }\n }\n }, pointerTypes);\n };\n }]);\n}\n\n// Left is negative X-coordinate, right is positive.\nmakeSwipeDirective('ngSwipeLeft', -1, 'swipeleft');\nmakeSwipeDirective('ngSwipeRight', 1, 'swiperight');\n\n\n\n})(window, window.angular);\n", - "/**\n * @license AngularJS v1.3.11\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {'use strict';\n\n/**\n * @description\n *\n * This object provides a utility for producing rich Error messages within\n * Angular. It can be called as follows:\n *\n * var exampleMinErr = minErr('example');\n * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);\n *\n * The above creates an instance of minErr in the example namespace. The\n * resulting error will have a namespaced error code of example.one. The\n * resulting error will replace {0} with the value of foo, and {1} with the\n * value of bar. The object is not restricted in the number of arguments it can\n * take.\n *\n * If fewer arguments are specified than necessary for interpolation, the extra\n * interpolation markers will be preserved in the final string.\n *\n * Since data will be parsed statically during a build step, some restrictions\n * are applied with respect to how minErr instances are created and called.\n * Instances should have names of the form namespaceMinErr for a minErr created\n * using minErr('namespace') . Error codes, namespaces and template strings\n * should all be static strings, not variables or general expressions.\n *\n * @param {string} module The namespace to use for the new minErr instance.\n * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning\n * error from returned function, for cases when a particular type of error is useful.\n * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance\n */\n\nfunction minErr(module, ErrorConstructor) {\n ErrorConstructor = ErrorConstructor || Error;\n return function() {\n var code = arguments[0],\n prefix = '[' + (module ? module + ':' : '') + code + '] ',\n template = arguments[1],\n templateArgs = arguments,\n\n message, i;\n\n message = prefix + template.replace(/\\{\\d+\\}/g, function(match) {\n var index = +match.slice(1, -1), arg;\n\n if (index + 2 < templateArgs.length) {\n return toDebugString(templateArgs[index + 2]);\n }\n return match;\n });\n\n message = message + '\\nhttp://errors.angularjs.org/1.3.11/' +\n (module ? module + '/' : '') + code;\n for (i = 2; i < arguments.length; i++) {\n message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +\n encodeURIComponent(toDebugString(arguments[i]));\n }\n return new ErrorConstructor(message);\n };\n}\n\n/* We need to tell jshint what variables are being exported */\n/* global angular: true,\n msie: true,\n jqLite: true,\n jQuery: true,\n slice: true,\n splice: true,\n push: true,\n toString: true,\n ngMinErr: true,\n angularModule: true,\n uid: true,\n REGEX_STRING_REGEXP: true,\n VALIDITY_STATE_PROPERTY: true,\n\n lowercase: true,\n uppercase: true,\n manualLowercase: true,\n manualUppercase: true,\n nodeName_: true,\n isArrayLike: true,\n forEach: true,\n sortedKeys: true,\n forEachSorted: true,\n reverseParams: true,\n nextUid: true,\n setHashKey: true,\n extend: true,\n int: true,\n inherit: true,\n noop: true,\n identity: true,\n valueFn: true,\n isUndefined: true,\n isDefined: true,\n isObject: true,\n isString: true,\n isNumber: true,\n isDate: true,\n isArray: true,\n isFunction: true,\n isRegExp: true,\n isWindow: true,\n isScope: true,\n isFile: true,\n isFormData: true,\n isBlob: true,\n isBoolean: true,\n isPromiseLike: true,\n trim: true,\n escapeForRegexp: true,\n isElement: true,\n makeMap: true,\n includes: true,\n arrayRemove: true,\n copy: true,\n shallowCopy: true,\n equals: true,\n csp: true,\n concat: true,\n sliceArgs: true,\n bind: true,\n toJsonReplacer: true,\n toJson: true,\n fromJson: true,\n startingTag: true,\n tryDecodeURIComponent: true,\n parseKeyValue: true,\n toKeyValue: true,\n encodeUriSegment: true,\n encodeUriQuery: true,\n angularInit: true,\n bootstrap: true,\n getTestability: true,\n snake_case: true,\n bindJQuery: true,\n assertArg: true,\n assertArgFn: true,\n assertNotHasOwnProperty: true,\n getter: true,\n getBlockNodes: true,\n hasOwnProperty: true,\n createMap: true,\n\n NODE_TYPE_ELEMENT: true,\n NODE_TYPE_TEXT: true,\n NODE_TYPE_COMMENT: true,\n NODE_TYPE_DOCUMENT: true,\n NODE_TYPE_DOCUMENT_FRAGMENT: true,\n*/\n\n////////////////////////////////////\n\n/**\n * @ngdoc module\n * @name ng\n * @module ng\n * @description\n *\n * # ng (core module)\n * The ng module is loaded by default when an AngularJS application is started. The module itself\n * contains the essential components for an AngularJS application to function. The table below\n * lists a high level breakdown of each of the services/factories, filters, directives and testing\n * components available within this core module.\n *\n *
\n */\n\nvar REGEX_STRING_REGEXP = /^\\/(.+)\\/([a-z]*)$/;\n\n// The name of a form control's ValidityState property.\n// This is used so that it's possible for internal tests to create mock ValidityStates.\nvar VALIDITY_STATE_PROPERTY = 'validity';\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @module ng\n * @kind function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @module ng\n * @kind function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n /* jshint bitwise: false */\n return isString(s)\n ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})\n : s;\n};\nvar manualUppercase = function(s) {\n /* jshint bitwise: false */\n return isString(s)\n ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})\n : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n lowercase = manualLowercase;\n uppercase = manualUppercase;\n}\n\n\nvar\n msie, // holds major version number for IE, or NaN if UA is not IE.\n jqLite, // delay binding since jQuery could be loaded after us.\n jQuery, // delay binding\n slice = [].slice,\n splice = [].splice,\n push = [].push,\n toString = Object.prototype.toString,\n ngMinErr = minErr('ng'),\n\n /** @name angular */\n angular = window.angular || (window.angular = {}),\n angularModule,\n uid = 0;\n\n/**\n * documentMode is an IE-only property\n * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx\n */\nmsie = document.documentMode;\n\n\n/**\n * @private\n * @param {*} obj\n * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,\n * String ...)\n */\nfunction isArrayLike(obj) {\n if (obj == null || isWindow(obj)) {\n return false;\n }\n\n var length = obj.length;\n\n if (obj.nodeType === NODE_TYPE_ELEMENT && length) {\n return true;\n }\n\n return isString(obj) || isArray(obj) || length === 0 ||\n typeof length === 'number' && length > 0 && (length - 1) in obj;\n}\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @module ng\n * @kind function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`\n * is the value of an object property or an array element, `key` is the object property key or\n * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.\n *\n * It is worth noting that `.forEach` does not iterate over inherited properties because it filters\n * using the `hasOwnProperty` method.\n *\n * Unlike ES262's\n * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),\n * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just\n * return the value provided.\n *\n ```js\n var values = {name: 'misko', gender: 'male'};\n var log = [];\n angular.forEach(values, function(value, key) {\n this.push(key + ': ' + value);\n }, log);\n expect(log).toEqual(['name: misko', 'gender: male']);\n ```\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\n\nfunction forEach(obj, iterator, context) {\n var key, length;\n if (obj) {\n if (isFunction(obj)) {\n for (key in obj) {\n // Need to check if hasOwnProperty exists,\n // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function\n if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {\n iterator.call(context, obj[key], key, obj);\n }\n }\n } else if (isArray(obj) || isArrayLike(obj)) {\n var isPrimitive = typeof obj !== 'object';\n for (key = 0, length = obj.length; key < length; key++) {\n if (isPrimitive || key in obj) {\n iterator.call(context, obj[key], key, obj);\n }\n }\n } else if (obj.forEach && obj.forEach !== forEach) {\n obj.forEach(iterator, context, obj);\n } else {\n for (key in obj) {\n if (obj.hasOwnProperty(key)) {\n iterator.call(context, obj[key], key, obj);\n }\n }\n }\n }\n return obj;\n}\n\nfunction sortedKeys(obj) {\n return Object.keys(obj).sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n var keys = sortedKeys(obj);\n for (var i = 0; i < keys.length; i++) {\n iterator.call(context, obj[keys[i]], keys[i]);\n }\n return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n return function(value, key) { iteratorFn(key, value); };\n}\n\n/**\n * A consistent way of creating unique IDs in angular.\n *\n * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before\n * we hit number precision issues in JavaScript.\n *\n * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M\n *\n * @returns {number} an unique alpha-numeric string\n */\nfunction nextUid() {\n return ++uid;\n}\n\n\n/**\n * Set or clear the hashkey for an object.\n * @param obj object\n * @param h the hashkey (!truthy to delete the hashkey)\n */\nfunction setHashKey(obj, h) {\n if (h) {\n obj.$$hashKey = h;\n }\n else {\n delete obj.$$hashKey;\n }\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @module ng\n * @kind function\n *\n * @description\n * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so\n * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.\n * Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy).\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n * @returns {Object} Reference to `dst`.\n */\nfunction extend(dst) {\n var h = dst.$$hashKey;\n\n for (var i = 1, ii = arguments.length; i < ii; i++) {\n var obj = arguments[i];\n if (obj) {\n var keys = Object.keys(obj);\n for (var j = 0, jj = keys.length; j < jj; j++) {\n var key = keys[j];\n dst[key] = obj[key];\n }\n }\n }\n\n setHashKey(dst, h);\n return dst;\n}\n\nfunction int(str) {\n return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n return extend(Object.create(parent), extra);\n}\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @module ng\n * @kind function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n ```js\n function foo(callback) {\n var result = calculateResult();\n (callback || angular.noop)(result);\n }\n ```\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @module ng\n * @kind function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n ```js\n function transformer(transformationFn, value) {\n return (transformationFn || angular.identity)(value);\n };\n ```\n * @param {*} value to be returned.\n * @returns {*} the value passed in.\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value) {return typeof value === 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value) {return typeof value !== 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects. Note that JavaScript arrays are objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value) {\n // http://jsperf.com/isobject4\n return value !== null && typeof value === 'object';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value) {return typeof value === 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value) {return typeof value === 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value) {\n return toString.call(value) === '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nvar isArray = Array.isArray;\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value) {return typeof value === 'function';}\n\n\n/**\n * Determines if a value is a regular expression object.\n *\n * @private\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `RegExp`.\n */\nfunction isRegExp(value) {\n return toString.call(value) === '[object RegExp]';\n}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n return obj && obj.window === obj;\n}\n\n\nfunction isScope(obj) {\n return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n return toString.call(obj) === '[object File]';\n}\n\n\nfunction isFormData(obj) {\n return toString.call(obj) === '[object FormData]';\n}\n\n\nfunction isBlob(obj) {\n return toString.call(obj) === '[object Blob]';\n}\n\n\nfunction isBoolean(value) {\n return typeof value === 'boolean';\n}\n\n\nfunction isPromiseLike(obj) {\n return obj && isFunction(obj.then);\n}\n\n\nvar trim = function(value) {\n return isString(value) ? value.trim() : value;\n};\n\n// Copied from:\n// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021\n// Prereq: s is a string.\nvar escapeForRegexp = function(s) {\n return s.replace(/([-()\\[\\]{}+?*.$\\^|,:#= 0)\n array.splice(index, 1);\n return value;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @module ng\n * @kind function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for arrays) or properties (for objects)\n * are deleted and then all elements/properties from the source are copied to it.\n * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.\n * * If `source` is identical to 'destination' an exception will be thrown.\n *\n * @param {*} source The source that will be used to make a copy.\n * Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n * provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n *\n * @example\n \n \n
\n
\n Name:
\n E-mail:
\n Gender: male\n female
\n \n \n
\n
form = {{user | json}}
\n
master = {{master | json}}
\n
\n\n \n
\n
\n */\nfunction copy(source, destination, stackSource, stackDest) {\n if (isWindow(source) || isScope(source)) {\n throw ngMinErr('cpws',\n \"Can't copy! Making copies of Window or Scope instances is not supported.\");\n }\n\n if (!destination) {\n destination = source;\n if (source) {\n if (isArray(source)) {\n destination = copy(source, [], stackSource, stackDest);\n } else if (isDate(source)) {\n destination = new Date(source.getTime());\n } else if (isRegExp(source)) {\n destination = new RegExp(source.source, source.toString().match(/[^\\/]*$/)[0]);\n destination.lastIndex = source.lastIndex;\n } else if (isObject(source)) {\n var emptyObject = Object.create(Object.getPrototypeOf(source));\n destination = copy(source, emptyObject, stackSource, stackDest);\n }\n }\n } else {\n if (source === destination) throw ngMinErr('cpi',\n \"Can't copy! Source and destination are identical.\");\n\n stackSource = stackSource || [];\n stackDest = stackDest || [];\n\n if (isObject(source)) {\n var index = stackSource.indexOf(source);\n if (index !== -1) return stackDest[index];\n\n stackSource.push(source);\n stackDest.push(destination);\n }\n\n var result;\n if (isArray(source)) {\n destination.length = 0;\n for (var i = 0; i < source.length; i++) {\n result = copy(source[i], null, stackSource, stackDest);\n if (isObject(source[i])) {\n stackSource.push(source[i]);\n stackDest.push(result);\n }\n destination.push(result);\n }\n } else {\n var h = destination.$$hashKey;\n if (isArray(destination)) {\n destination.length = 0;\n } else {\n forEach(destination, function(value, key) {\n delete destination[key];\n });\n }\n for (var key in source) {\n if (source.hasOwnProperty(key)) {\n result = copy(source[key], null, stackSource, stackDest);\n if (isObject(source[key])) {\n stackSource.push(source[key]);\n stackDest.push(result);\n }\n destination[key] = result;\n }\n }\n setHashKey(destination,h);\n }\n\n }\n return destination;\n}\n\n/**\n * Creates a shallow copy of an object, an array or a primitive.\n *\n * Assumes that there are no proto properties for objects.\n */\nfunction shallowCopy(src, dst) {\n if (isArray(src)) {\n dst = dst || [];\n\n for (var i = 0, ii = src.length; i < ii; i++) {\n dst[i] = src[i];\n }\n } else if (isObject(src)) {\n dst = dst || {};\n\n for (var key in src) {\n if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {\n dst[key] = src[key];\n }\n }\n }\n\n return dst || src;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @module ng\n * @kind function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, regular\n * expressions, arrays and objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties are equal by\n * comparing them with `angular.equals`.\n * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)\n * * Both values represent the same regular expression (In JavaScript,\n * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual\n * representation matches).\n *\n * During a property comparison, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only by identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n if (o1 === o2) return true;\n if (o1 === null || o2 === null) return false;\n if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n if (t1 == t2) {\n if (t1 == 'object') {\n if (isArray(o1)) {\n if (!isArray(o2)) return false;\n if ((length = o1.length) == o2.length) {\n for (key = 0; key < length; key++) {\n if (!equals(o1[key], o2[key])) return false;\n }\n return true;\n }\n } else if (isDate(o1)) {\n if (!isDate(o2)) return false;\n return equals(o1.getTime(), o2.getTime());\n } else if (isRegExp(o1) && isRegExp(o2)) {\n return o1.toString() == o2.toString();\n } else {\n if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;\n keySet = {};\n for (key in o1) {\n if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n if (!equals(o1[key], o2[key])) return false;\n keySet[key] = true;\n }\n for (key in o2) {\n if (!keySet.hasOwnProperty(key) &&\n key.charAt(0) !== '$' &&\n o2[key] !== undefined &&\n !isFunction(o2[key])) return false;\n }\n return true;\n }\n }\n }\n return false;\n}\n\nvar csp = function() {\n if (isDefined(csp.isActive_)) return csp.isActive_;\n\n var active = !!(document.querySelector('[ng-csp]') ||\n document.querySelector('[data-ng-csp]'));\n\n if (!active) {\n try {\n /* jshint -W031, -W054 */\n new Function('');\n /* jshint +W031, +W054 */\n } catch (e) {\n active = true;\n }\n }\n\n return (csp.isActive_ = active);\n};\n\n\n\nfunction concat(array1, array2, index) {\n return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n return slice.call(args, startIndex || 0);\n}\n\n\n/* jshint -W101 */\n/**\n * @ngdoc function\n * @name angular.bind\n * @module ng\n * @kind function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are prebound to the function. This feature is also\n * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as\n * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\n/* jshint +W101 */\nfunction bind(self, fn) {\n var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n if (isFunction(fn) && !(fn instanceof RegExp)) {\n return curryArgs.length\n ? function() {\n return arguments.length\n ? fn.apply(self, concat(curryArgs, arguments, 0))\n : fn.apply(self, curryArgs);\n }\n : function() {\n return arguments.length\n ? fn.apply(self, arguments)\n : fn.call(self);\n };\n } else {\n // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n return fn;\n }\n}\n\n\nfunction toJsonReplacer(key, value) {\n var val = value;\n\n if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {\n val = undefined;\n } else if (isWindow(value)) {\n val = '$WINDOW';\n } else if (value && document === value) {\n val = '$DOCUMENT';\n } else if (isScope(value)) {\n val = '$SCOPE';\n }\n\n return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @module ng\n * @kind function\n *\n * @description\n * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be\n * stripped since angular uses this notation internally.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2).\n * @returns {string|undefined} JSON-ified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n if (typeof obj === 'undefined') return undefined;\n if (!isNumber(pretty)) {\n pretty = pretty ? 2 : null;\n }\n return JSON.stringify(obj, toJsonReplacer, pretty);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @module ng\n * @kind function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|string|number} Deserialized JSON string.\n */\nfunction fromJson(json) {\n return isString(json)\n ? JSON.parse(json)\n : json;\n}\n\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n element = jqLite(element).clone();\n try {\n // turns out IE does not let you set .html() on elements which\n // are not allowed to have children. So we just ignore it.\n element.empty();\n } catch (e) {}\n var elemHtml = jqLite('
').append(element).html();\n try {\n return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :\n elemHtml.\n match(/^(<[^>]+>)/)[1].\n replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n } catch (e) {\n return lowercase(elemHtml);\n }\n\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Tries to decode the URI component without throwing an exception.\n *\n * @private\n * @param str value potential URI component to check.\n * @returns {boolean} True if `value` can be decoded\n * with the decodeURIComponent function.\n */\nfunction tryDecodeURIComponent(value) {\n try {\n return decodeURIComponent(value);\n } catch (e) {\n // Ignore any invalid uri component\n }\n}\n\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns {Object.}\n */\nfunction parseKeyValue(/**string*/keyValue) {\n var obj = {}, key_value, key;\n forEach((keyValue || \"\").split('&'), function(keyValue) {\n if (keyValue) {\n key_value = keyValue.replace(/\\+/g,'%20').split('=');\n key = tryDecodeURIComponent(key_value[0]);\n if (isDefined(key)) {\n var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;\n if (!hasOwnProperty.call(obj, key)) {\n obj[key] = val;\n } else if (isArray(obj[key])) {\n obj[key].push(val);\n } else {\n obj[key] = [obj[key],val];\n }\n }\n }\n });\n return obj;\n}\n\nfunction toKeyValue(obj) {\n var parts = [];\n forEach(obj, function(value, key) {\n if (isArray(value)) {\n forEach(value, function(arrayValue) {\n parts.push(encodeUriQuery(key, true) +\n (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));\n });\n } else {\n parts.push(encodeUriQuery(key, true) +\n (value === true ? '' : '=' + encodeUriQuery(value, true)));\n }\n });\n return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n * segment = *pchar\n * pchar = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n * pct-encoded = \"%\" HEXDIG HEXDIG\n * unreserved = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n * sub-delims = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n * / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n return encodeUriQuery(val, true).\n replace(/%26/gi, '&').\n replace(/%3D/gi, '=').\n replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n * query = *( pchar / \"/\" / \"?\" )\n * pchar = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n * unreserved = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n * pct-encoded = \"%\" HEXDIG HEXDIG\n * sub-delims = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n * / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n return encodeURIComponent(val).\n replace(/%40/gi, '@').\n replace(/%3A/gi, ':').\n replace(/%24/g, '$').\n replace(/%2C/gi, ',').\n replace(/%3B/gi, ';').\n replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));\n}\n\nvar ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];\n\nfunction getNgAttribute(element, ngAttr) {\n var attr, i, ii = ngAttrPrefixes.length;\n element = jqLite(element);\n for (i = 0; i < ii; ++i) {\n attr = ngAttrPrefixes[i] + ngAttr;\n if (isString(attr = element.attr(attr))) {\n return attr;\n }\n }\n return null;\n}\n\n/**\n * @ngdoc directive\n * @name ngApp\n * @module ng\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n * {@link angular.module module} name to load.\n * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be\n * created in \"strict-di\" mode. This means that the application will fail to invoke functions which\n * do not use explicit function annotation (and are thus unsuitable for minification), as described\n * in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in\n * tracking down the root of these bugs.\n *\n * @description\n *\n * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive\n * designates the **root element** of the application and is typically placed near the root element\n * of the page - e.g. on the `` or `` tags.\n *\n * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`\n * found in the document will be used to define the root element to auto-bootstrap as an\n * application. To run multiple applications in an HTML document you must manually bootstrap them using\n * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.\n *\n * You can specify an **AngularJS module** to be used as the root module for the application. This\n * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It\n * should contain the application code needed or have dependencies on other modules that will\n * contain the code. See {@link angular.module} for more information.\n *\n * In the example below if the `ngApp` directive were not placed on the `html` element then the\n * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`\n * would not be resolved to `3`.\n *\n * `ngApp` is the easiest, and most common way to bootstrap an application.\n *\n \n \n
\n I can add: {{a}} + {{b}} = {{ a+b }}\n
\n
\n \n angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {\n $scope.a = 1;\n $scope.b = 2;\n });\n \n
\n *\n * Using `ngStrictDi`, you would see something like this:\n *\n \n \n
\n
\n I can add: {{a}} + {{b}} = {{ a+b }}\n\n

This renders because the controller does not fail to\n instantiate, by using explicit annotation style (see\n script.js for details)\n

\n
\n\n
\n Name:
\n Hello, {{name}}!\n\n

This renders because the controller does not fail to\n instantiate, by using explicit annotation style\n (see script.js for details)\n

\n
\n\n
\n I can add: {{a}} + {{b}} = {{ a+b }}\n\n

The controller could not be instantiated, due to relying\n on automatic function annotations (which are disabled in\n strict mode). As such, the content of this section is not\n interpolated, and there should be an error in your web console.\n

\n
\n
\n
\n \n angular.module('ngAppStrictDemo', [])\n // BadController will fail to instantiate, due to relying on automatic function annotation,\n // rather than an explicit annotation\n .controller('BadController', function($scope) {\n $scope.a = 1;\n $scope.b = 2;\n })\n // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,\n // due to using explicit annotations using the array style and $inject property, respectively.\n .controller('GoodController1', ['$scope', function($scope) {\n $scope.a = 1;\n $scope.b = 2;\n }])\n .controller('GoodController2', GoodController2);\n function GoodController2($scope) {\n $scope.name = \"World\";\n }\n GoodController2.$inject = ['$scope'];\n \n \n div[ng-controller] {\n margin-bottom: 1em;\n -webkit-border-radius: 4px;\n border-radius: 4px;\n border: 1px solid;\n padding: .5em;\n }\n div[ng-controller^=Good] {\n border-color: #d6e9c6;\n background-color: #dff0d8;\n color: #3c763d;\n }\n div[ng-controller^=Bad] {\n border-color: #ebccd1;\n background-color: #f2dede;\n color: #a94442;\n margin-bottom: 0;\n }\n \n
\n */\nfunction angularInit(element, bootstrap) {\n var appElement,\n module,\n config = {};\n\n // The element `element` has priority over any other element\n forEach(ngAttrPrefixes, function(prefix) {\n var name = prefix + 'app';\n\n if (!appElement && element.hasAttribute && element.hasAttribute(name)) {\n appElement = element;\n module = element.getAttribute(name);\n }\n });\n forEach(ngAttrPrefixes, function(prefix) {\n var name = prefix + 'app';\n var candidate;\n\n if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\\\:') + ']'))) {\n appElement = candidate;\n module = candidate.getAttribute(name);\n }\n });\n if (appElement) {\n config.strictDi = getNgAttribute(appElement, \"strict-di\") !== null;\n bootstrap(appElement, module ? [module] : [], config);\n }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @module ng\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually.\n * They must use {@link ng.directive:ngApp ngApp}.\n *\n * Angular will detect if it has been loaded into the browser more than once and only allow the\n * first loaded script to be bootstrapped and will report a warning to the browser console for\n * each of the subsequent scripts. This prevents strange results in applications, where otherwise\n * multiple instances of Angular try to work on the DOM.\n *\n * ```html\n * \n * \n * \n *
\n * {{greeting}}\n *
\n *\n * \n * \n * \n * \n * ```\n *\n * @param {DOMElement} element DOM element which is the root of angular application.\n * @param {Array=} modules an array of modules to load into the application.\n * Each item in the array should be the name of a predefined module or a (DI annotated)\n * function that will be invoked by the injector as a `config` block.\n * See: {@link angular.module modules}\n * @param {Object=} config an object for defining configuration options for the application. The\n * following keys are supported:\n *\n * * `strictDi` - disable automatic function annotation for the application. This is meant to\n * assist in finding bugs which break minified code. Defaults to `false`.\n *\n * @returns {auto.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules, config) {\n if (!isObject(config)) config = {};\n var defaultConfig = {\n strictDi: false\n };\n config = extend(defaultConfig, config);\n var doBootstrap = function() {\n element = jqLite(element);\n\n if (element.injector()) {\n var tag = (element[0] === document) ? 'document' : startingTag(element);\n //Encode angle brackets to prevent input from being sanitized to empty string #8683\n throw ngMinErr(\n 'btstrpd',\n \"App Already Bootstrapped with this Element '{0}'\",\n tag.replace(//,'>'));\n }\n\n modules = modules || [];\n modules.unshift(['$provide', function($provide) {\n $provide.value('$rootElement', element);\n }]);\n\n if (config.debugInfoEnabled) {\n // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`.\n modules.push(['$compileProvider', function($compileProvider) {\n $compileProvider.debugInfoEnabled(true);\n }]);\n }\n\n modules.unshift('ng');\n var injector = createInjector(modules, config.strictDi);\n injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',\n function bootstrapApply(scope, element, compile, injector) {\n scope.$apply(function() {\n element.data('$injector', injector);\n compile(element)(scope);\n });\n }]\n );\n return injector;\n };\n\n var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/;\n var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;\n\n if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) {\n config.debugInfoEnabled = true;\n window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, '');\n }\n\n if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {\n return doBootstrap();\n }\n\n window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');\n angular.resumeBootstrap = function(extraModules) {\n forEach(extraModules, function(module) {\n modules.push(module);\n });\n doBootstrap();\n };\n}\n\n/**\n * @ngdoc function\n * @name angular.reloadWithDebugInfo\n * @module ng\n * @description\n * Use this function to reload the current application with debug information turned on.\n * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`.\n *\n * See {@link ng.$compileProvider#debugInfoEnabled} for more.\n */\nfunction reloadWithDebugInfo() {\n window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name;\n window.location.reload();\n}\n\n/**\n * @name angular.getTestability\n * @module ng\n * @description\n * Get the testability service for the instance of Angular on the given\n * element.\n * @param {DOMElement} element DOM element which is the root of angular application.\n */\nfunction getTestability(rootElement) {\n var injector = angular.element(rootElement).injector();\n if (!injector) {\n throw ngMinErr('test',\n 'no injector found for element argument to getTestability');\n }\n return injector.get('$$testability');\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator) {\n separator = separator || '_';\n return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n return (pos ? separator : '') + letter.toLowerCase();\n });\n}\n\nvar bindJQueryFired = false;\nvar skipDestroyOnNextJQueryCleanData;\nfunction bindJQuery() {\n var originalCleanData;\n\n if (bindJQueryFired) {\n return;\n }\n\n // bind to jQuery if present;\n jQuery = window.jQuery;\n // Use jQuery if it exists with proper functionality, otherwise default to us.\n // Angular 1.2+ requires jQuery 1.7+ for on()/off() support.\n // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older\n // versions. It will not work for sure with jQuery <1.7, though.\n if (jQuery && jQuery.fn.on) {\n jqLite = jQuery;\n extend(jQuery.fn, {\n scope: JQLitePrototype.scope,\n isolateScope: JQLitePrototype.isolateScope,\n controller: JQLitePrototype.controller,\n injector: JQLitePrototype.injector,\n inheritedData: JQLitePrototype.inheritedData\n });\n\n // All nodes removed from the DOM via various jQuery APIs like .remove()\n // are passed through jQuery.cleanData. Monkey-patch this method to fire\n // the $destroy event on all removed nodes.\n originalCleanData = jQuery.cleanData;\n jQuery.cleanData = function(elems) {\n var events;\n if (!skipDestroyOnNextJQueryCleanData) {\n for (var i = 0, elem; (elem = elems[i]) != null; i++) {\n events = jQuery._data(elem, \"events\");\n if (events && events.$destroy) {\n jQuery(elem).triggerHandler('$destroy');\n }\n }\n } else {\n skipDestroyOnNextJQueryCleanData = false;\n }\n originalCleanData(elems);\n };\n } else {\n jqLite = JQLite;\n }\n\n angular.element = jqLite;\n\n // Prevent double-proxying.\n bindJQueryFired = true;\n}\n\n/**\n * throw error if the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n if (!arg) {\n throw ngMinErr('areq', \"Argument '{0}' is {1}\", (name || '?'), (reason || \"required\"));\n }\n return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n if (acceptArrayAnnotation && isArray(arg)) {\n arg = arg[arg.length - 1];\n }\n\n assertArg(isFunction(arg), name, 'not a function, got ' +\n (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));\n return arg;\n}\n\n/**\n * throw error if the name given is hasOwnProperty\n * @param {String} name the name to test\n * @param {String} context the context in which the name is used, such as module or directive\n */\nfunction assertNotHasOwnProperty(name, context) {\n if (name === 'hasOwnProperty') {\n throw ngMinErr('badname', \"hasOwnProperty is not a valid {0} name\", context);\n }\n}\n\n/**\n * Return the value accessible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {String} path path to traverse\n * @param {boolean} [bindFnToScope=true]\n * @returns {Object} value as accessible by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n if (!path) return obj;\n var keys = path.split('.');\n var key;\n var lastInstance = obj;\n var len = keys.length;\n\n for (var i = 0; i < len; i++) {\n key = keys[i];\n if (obj) {\n obj = (lastInstance = obj)[key];\n }\n }\n if (!bindFnToScope && isFunction(obj)) {\n return bind(lastInstance, obj);\n }\n return obj;\n}\n\n/**\n * Return the DOM siblings between the first and last node in the given array.\n * @param {Array} array like object\n * @returns {jqLite} jqLite collection containing the nodes\n */\nfunction getBlockNodes(nodes) {\n // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original\n // collection, otherwise update the original collection.\n var node = nodes[0];\n var endNode = nodes[nodes.length - 1];\n var blockNodes = [node];\n\n do {\n node = node.nextSibling;\n if (!node) break;\n blockNodes.push(node);\n } while (node !== endNode);\n\n return jqLite(blockNodes);\n}\n\n\n/**\n * Creates a new object without a prototype. This object is useful for lookup without having to\n * guard against prototypically inherited properties via hasOwnProperty.\n *\n * Related micro-benchmarks:\n * - http://jsperf.com/object-create2\n * - http://jsperf.com/proto-map-lookup/2\n * - http://jsperf.com/for-in-vs-object-keys2\n *\n * @returns {Object}\n */\nfunction createMap() {\n return Object.create(null);\n}\n\nvar NODE_TYPE_ELEMENT = 1;\nvar NODE_TYPE_TEXT = 3;\nvar NODE_TYPE_COMMENT = 8;\nvar NODE_TYPE_DOCUMENT = 9;\nvar NODE_TYPE_DOCUMENT_FRAGMENT = 11;\n\n/**\n * @ngdoc type\n * @name angular.Module\n * @module ng\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n var $injectorMinErr = minErr('$injector');\n var ngMinErr = minErr('ng');\n\n function ensure(obj, name, factory) {\n return obj[name] || (obj[name] = factory());\n }\n\n var angular = ensure(window, 'angular', Object);\n\n // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap\n angular.$$minErr = angular.$$minErr || minErr;\n\n return ensure(angular, 'module', function() {\n /** @type {Object.} */\n var modules = {};\n\n /**\n * @ngdoc function\n * @name angular.module\n * @module ng\n * @description\n *\n * The `angular.module` is a global place for creating, registering and retrieving Angular\n * modules.\n * All modules (angular core or 3rd party) that should be available to an application must be\n * registered using this mechanism.\n *\n * When passed two or more arguments, a new module is created. If passed only one argument, an\n * existing module (the name passed as the first argument to `module`) is retrieved.\n *\n *\n * # Module\n *\n * A module is a collection of services, directives, controllers, filters, and configuration information.\n * `angular.module` is used to configure the {@link auto.$injector $injector}.\n *\n * ```js\n * // Create a new module\n * var myModule = angular.module('myModule', []);\n *\n * // register a new service\n * myModule.value('appName', 'MyCoolApp');\n *\n * // configure existing services inside initialization blocks.\n * myModule.config(['$locationProvider', function($locationProvider) {\n * // Configure existing providers\n * $locationProvider.hashPrefix('!');\n * }]);\n * ```\n *\n * Then you can create an injector and load your modules like this:\n *\n * ```js\n * var injector = angular.injector(['ng', 'myModule'])\n * ```\n *\n * However it's more likely that you'll just use\n * {@link ng.directive:ngApp ngApp} or\n * {@link angular.bootstrap} to simplify this process for you.\n *\n * @param {!string} name The name of the module to create or retrieve.\n * @param {!Array.=} requires If specified then new module is being created. If\n * unspecified then the module is being retrieved for further configuration.\n * @param {Function=} configFn Optional configuration function for the module. Same as\n * {@link angular.Module#config Module#config()}.\n * @returns {module} new module with the {@link angular.Module} api.\n */\n return function module(name, requires, configFn) {\n var assertNotHasOwnProperty = function(name, context) {\n if (name === 'hasOwnProperty') {\n throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);\n }\n };\n\n assertNotHasOwnProperty(name, 'module');\n if (requires && modules.hasOwnProperty(name)) {\n modules[name] = null;\n }\n return ensure(modules, name, function() {\n if (!requires) {\n throw $injectorMinErr('nomod', \"Module '{0}' is not available! You either misspelled \" +\n \"the module name or forgot to load it. If registering a module ensure that you \" +\n \"specify the dependencies as the second argument.\", name);\n }\n\n /** @type {!Array.>} */\n var invokeQueue = [];\n\n /** @type {!Array.} */\n var configBlocks = [];\n\n /** @type {!Array.} */\n var runBlocks = [];\n\n var config = invokeLater('$injector', 'invoke', 'push', configBlocks);\n\n /** @type {angular.Module} */\n var moduleInstance = {\n // Private state\n _invokeQueue: invokeQueue,\n _configBlocks: configBlocks,\n _runBlocks: runBlocks,\n\n /**\n * @ngdoc property\n * @name angular.Module#requires\n * @module ng\n *\n * @description\n * Holds the list of modules which the injector will load before the current module is\n * loaded.\n */\n requires: requires,\n\n /**\n * @ngdoc property\n * @name angular.Module#name\n * @module ng\n *\n * @description\n * Name of the module.\n */\n name: name,\n\n\n /**\n * @ngdoc method\n * @name angular.Module#provider\n * @module ng\n * @param {string} name service name\n * @param {Function} providerType Construction function for creating new instance of the\n * service.\n * @description\n * See {@link auto.$provide#provider $provide.provider()}.\n */\n provider: invokeLater('$provide', 'provider'),\n\n /**\n * @ngdoc method\n * @name angular.Module#factory\n * @module ng\n * @param {string} name service name\n * @param {Function} providerFunction Function for creating new instance of the service.\n * @description\n * See {@link auto.$provide#factory $provide.factory()}.\n */\n factory: invokeLater('$provide', 'factory'),\n\n /**\n * @ngdoc method\n * @name angular.Module#service\n * @module ng\n * @param {string} name service name\n * @param {Function} constructor A constructor function that will be instantiated.\n * @description\n * See {@link auto.$provide#service $provide.service()}.\n */\n service: invokeLater('$provide', 'service'),\n\n /**\n * @ngdoc method\n * @name angular.Module#value\n * @module ng\n * @param {string} name service name\n * @param {*} object Service instance object.\n * @description\n * See {@link auto.$provide#value $provide.value()}.\n */\n value: invokeLater('$provide', 'value'),\n\n /**\n * @ngdoc method\n * @name angular.Module#constant\n * @module ng\n * @param {string} name constant name\n * @param {*} object Constant value.\n * @description\n * Because the constant are fixed, they get applied before other provide methods.\n * See {@link auto.$provide#constant $provide.constant()}.\n */\n constant: invokeLater('$provide', 'constant', 'unshift'),\n\n /**\n * @ngdoc method\n * @name angular.Module#animation\n * @module ng\n * @param {string} name animation name\n * @param {Function} animationFactory Factory function for creating new instance of an\n * animation.\n * @description\n *\n * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.\n *\n *\n * Defines an animation hook that can be later used with\n * {@link ngAnimate.$animate $animate} service and directives that use this service.\n *\n * ```js\n * module.animation('.animation-name', function($inject1, $inject2) {\n * return {\n * eventName : function(element, done) {\n * //code to run the animation\n * //once complete, then run done()\n * return function cancellationFunction(element) {\n * //code to cancel the animation\n * }\n * }\n * }\n * })\n * ```\n *\n * See {@link ng.$animateProvider#register $animateProvider.register()} and\n * {@link ngAnimate ngAnimate module} for more information.\n */\n animation: invokeLater('$animateProvider', 'register'),\n\n /**\n * @ngdoc method\n * @name angular.Module#filter\n * @module ng\n * @param {string} name Filter name.\n * @param {Function} filterFactory Factory function for creating new instance of filter.\n * @description\n * See {@link ng.$filterProvider#register $filterProvider.register()}.\n */\n filter: invokeLater('$filterProvider', 'register'),\n\n /**\n * @ngdoc method\n * @name angular.Module#controller\n * @module ng\n * @param {string|Object} name Controller name, or an object map of controllers where the\n * keys are the names and the values are the constructors.\n * @param {Function} constructor Controller constructor function.\n * @description\n * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n */\n controller: invokeLater('$controllerProvider', 'register'),\n\n /**\n * @ngdoc method\n * @name angular.Module#directive\n * @module ng\n * @param {string|Object} name Directive name, or an object map of directives where the\n * keys are the names and the values are the factories.\n * @param {Function} directiveFactory Factory function for creating new instance of\n * directives.\n * @description\n * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n */\n directive: invokeLater('$compileProvider', 'directive'),\n\n /**\n * @ngdoc method\n * @name angular.Module#config\n * @module ng\n * @param {Function} configFn Execute this function on module load. Useful for service\n * configuration.\n * @description\n * Use this method to register work which needs to be performed on module loading.\n * For more about how to configure services, see\n * {@link providers#provider-recipe Provider Recipe}.\n */\n config: config,\n\n /**\n * @ngdoc method\n * @name angular.Module#run\n * @module ng\n * @param {Function} initializationFn Execute this function after injector creation.\n * Useful for application initialization.\n * @description\n * Use this method to register work which should be performed when the injector is done\n * loading all modules.\n */\n run: function(block) {\n runBlocks.push(block);\n return this;\n }\n };\n\n if (configFn) {\n config(configFn);\n }\n\n return moduleInstance;\n\n /**\n * @param {string} provider\n * @param {string} method\n * @param {String=} insertMethod\n * @returns {angular.Module}\n */\n function invokeLater(provider, method, insertMethod, queue) {\n if (!queue) queue = invokeQueue;\n return function() {\n queue[insertMethod || 'push']([provider, method, arguments]);\n return moduleInstance;\n };\n }\n });\n };\n });\n\n}\n\n/* global: toDebugString: true */\n\nfunction serializeObject(obj) {\n var seen = [];\n\n return JSON.stringify(obj, function(key, val) {\n val = toJsonReplacer(key, val);\n if (isObject(val)) {\n\n if (seen.indexOf(val) >= 0) return '<>';\n\n seen.push(val);\n }\n return val;\n });\n}\n\nfunction toDebugString(obj) {\n if (typeof obj === 'function') {\n return obj.toString().replace(/ \\{[\\s\\S]*$/, '');\n } else if (typeof obj === 'undefined') {\n return 'undefined';\n } else if (typeof obj !== 'string') {\n return serializeObject(obj);\n }\n return obj;\n}\n\n/* global angularModule: true,\n version: true,\n\n $LocaleProvider,\n $CompileProvider,\n\n htmlAnchorDirective,\n inputDirective,\n inputDirective,\n formDirective,\n scriptDirective,\n selectDirective,\n styleDirective,\n optionDirective,\n ngBindDirective,\n ngBindHtmlDirective,\n ngBindTemplateDirective,\n ngClassDirective,\n ngClassEvenDirective,\n ngClassOddDirective,\n ngCspDirective,\n ngCloakDirective,\n ngControllerDirective,\n ngFormDirective,\n ngHideDirective,\n ngIfDirective,\n ngIncludeDirective,\n ngIncludeFillContentDirective,\n ngInitDirective,\n ngNonBindableDirective,\n ngPluralizeDirective,\n ngRepeatDirective,\n ngShowDirective,\n ngStyleDirective,\n ngSwitchDirective,\n ngSwitchWhenDirective,\n ngSwitchDefaultDirective,\n ngOptionsDirective,\n ngTranscludeDirective,\n ngModelDirective,\n ngListDirective,\n ngChangeDirective,\n patternDirective,\n patternDirective,\n requiredDirective,\n requiredDirective,\n minlengthDirective,\n minlengthDirective,\n maxlengthDirective,\n maxlengthDirective,\n ngValueDirective,\n ngModelOptionsDirective,\n ngAttributeAliasDirectives,\n ngEventDirectives,\n\n $AnchorScrollProvider,\n $AnimateProvider,\n $BrowserProvider,\n $CacheFactoryProvider,\n $ControllerProvider,\n $DocumentProvider,\n $ExceptionHandlerProvider,\n $FilterProvider,\n $InterpolateProvider,\n $IntervalProvider,\n $HttpProvider,\n $HttpBackendProvider,\n $LocationProvider,\n $LogProvider,\n $ParseProvider,\n $RootScopeProvider,\n $QProvider,\n $$QProvider,\n $$SanitizeUriProvider,\n $SceProvider,\n $SceDelegateProvider,\n $SnifferProvider,\n $TemplateCacheProvider,\n $TemplateRequestProvider,\n $$TestabilityProvider,\n $TimeoutProvider,\n $$RAFProvider,\n $$AsyncCallbackProvider,\n $WindowProvider,\n $$jqLiteProvider\n*/\n\n\n/**\n * @ngdoc object\n * @name angular.version\n * @module ng\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n full: '1.3.11', // all of these placeholder strings will be replaced by grunt's\n major: 1, // package task\n minor: 3,\n dot: 11,\n codeName: 'spiffy-manatee'\n};\n\n\nfunction publishExternalAPI(angular) {\n extend(angular, {\n 'bootstrap': bootstrap,\n 'copy': copy,\n 'extend': extend,\n 'equals': equals,\n 'element': jqLite,\n 'forEach': forEach,\n 'injector': createInjector,\n 'noop': noop,\n 'bind': bind,\n 'toJson': toJson,\n 'fromJson': fromJson,\n 'identity': identity,\n 'isUndefined': isUndefined,\n 'isDefined': isDefined,\n 'isString': isString,\n 'isFunction': isFunction,\n 'isObject': isObject,\n 'isNumber': isNumber,\n 'isElement': isElement,\n 'isArray': isArray,\n 'version': version,\n 'isDate': isDate,\n 'lowercase': lowercase,\n 'uppercase': uppercase,\n 'callbacks': {counter: 0},\n 'getTestability': getTestability,\n '$$minErr': minErr,\n '$$csp': csp,\n 'reloadWithDebugInfo': reloadWithDebugInfo\n });\n\n angularModule = setupModuleLoader(window);\n try {\n angularModule('ngLocale');\n } catch (e) {\n angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n }\n\n angularModule('ng', ['ngLocale'], ['$provide',\n function ngModule($provide) {\n // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.\n $provide.provider({\n $$sanitizeUri: $$SanitizeUriProvider\n });\n $provide.provider('$compile', $CompileProvider).\n directive({\n a: htmlAnchorDirective,\n input: inputDirective,\n textarea: inputDirective,\n form: formDirective,\n script: scriptDirective,\n select: selectDirective,\n style: styleDirective,\n option: optionDirective,\n ngBind: ngBindDirective,\n ngBindHtml: ngBindHtmlDirective,\n ngBindTemplate: ngBindTemplateDirective,\n ngClass: ngClassDirective,\n ngClassEven: ngClassEvenDirective,\n ngClassOdd: ngClassOddDirective,\n ngCloak: ngCloakDirective,\n ngController: ngControllerDirective,\n ngForm: ngFormDirective,\n ngHide: ngHideDirective,\n ngIf: ngIfDirective,\n ngInclude: ngIncludeDirective,\n ngInit: ngInitDirective,\n ngNonBindable: ngNonBindableDirective,\n ngPluralize: ngPluralizeDirective,\n ngRepeat: ngRepeatDirective,\n ngShow: ngShowDirective,\n ngStyle: ngStyleDirective,\n ngSwitch: ngSwitchDirective,\n ngSwitchWhen: ngSwitchWhenDirective,\n ngSwitchDefault: ngSwitchDefaultDirective,\n ngOptions: ngOptionsDirective,\n ngTransclude: ngTranscludeDirective,\n ngModel: ngModelDirective,\n ngList: ngListDirective,\n ngChange: ngChangeDirective,\n pattern: patternDirective,\n ngPattern: patternDirective,\n required: requiredDirective,\n ngRequired: requiredDirective,\n minlength: minlengthDirective,\n ngMinlength: minlengthDirective,\n maxlength: maxlengthDirective,\n ngMaxlength: maxlengthDirective,\n ngValue: ngValueDirective,\n ngModelOptions: ngModelOptionsDirective\n }).\n directive({\n ngInclude: ngIncludeFillContentDirective\n }).\n directive(ngAttributeAliasDirectives).\n directive(ngEventDirectives);\n $provide.provider({\n $anchorScroll: $AnchorScrollProvider,\n $animate: $AnimateProvider,\n $browser: $BrowserProvider,\n $cacheFactory: $CacheFactoryProvider,\n $controller: $ControllerProvider,\n $document: $DocumentProvider,\n $exceptionHandler: $ExceptionHandlerProvider,\n $filter: $FilterProvider,\n $interpolate: $InterpolateProvider,\n $interval: $IntervalProvider,\n $http: $HttpProvider,\n $httpBackend: $HttpBackendProvider,\n $location: $LocationProvider,\n $log: $LogProvider,\n $parse: $ParseProvider,\n $rootScope: $RootScopeProvider,\n $q: $QProvider,\n $$q: $$QProvider,\n $sce: $SceProvider,\n $sceDelegate: $SceDelegateProvider,\n $sniffer: $SnifferProvider,\n $templateCache: $TemplateCacheProvider,\n $templateRequest: $TemplateRequestProvider,\n $$testability: $$TestabilityProvider,\n $timeout: $TimeoutProvider,\n $window: $WindowProvider,\n $$rAF: $$RAFProvider,\n $$asyncCallback: $$AsyncCallbackProvider,\n $$jqLite: $$jqLiteProvider\n });\n }\n ]);\n}\n\n/* global JQLitePrototype: true,\n addEventListenerFn: true,\n removeEventListenerFn: true,\n BOOLEAN_ATTR: true,\n ALIASED_ATTR: true,\n*/\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @module ng\n * @kind function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n *\n * If jQuery is available, `angular.element` is an alias for the\n * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`\n * delegates to Angular's built-in subset of jQuery, called \"jQuery lite\" or \"jqLite.\"\n *\n *
jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most\n * commonly needed functionality with the goal of having a very small footprint.
\n *\n * To use jQuery, simply load it before `DOMContentLoaded` event fired.\n *\n *
**Note:** all element references in Angular are always wrapped with jQuery or\n * jqLite; they are never raw DOM references.
\n *\n * ## Angular's jqLite\n * jqLite provides only the following jQuery methods:\n *\n * - [`addClass()`](http://api.jquery.com/addClass/)\n * - [`after()`](http://api.jquery.com/after/)\n * - [`append()`](http://api.jquery.com/append/)\n * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters\n * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData\n * - [`children()`](http://api.jquery.com/children/) - Does not support selectors\n * - [`clone()`](http://api.jquery.com/clone/)\n * - [`contents()`](http://api.jquery.com/contents/)\n * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`\n * - [`data()`](http://api.jquery.com/data/)\n * - [`detach()`](http://api.jquery.com/detach/)\n * - [`empty()`](http://api.jquery.com/empty/)\n * - [`eq()`](http://api.jquery.com/eq/)\n * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name\n * - [`hasClass()`](http://api.jquery.com/hasClass/)\n * - [`html()`](http://api.jquery.com/html/)\n * - [`next()`](http://api.jquery.com/next/) - Does not support selectors\n * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData\n * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors\n * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors\n * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors\n * - [`prepend()`](http://api.jquery.com/prepend/)\n * - [`prop()`](http://api.jquery.com/prop/)\n * - [`ready()`](http://api.jquery.com/ready/)\n * - [`remove()`](http://api.jquery.com/remove/)\n * - [`removeAttr()`](http://api.jquery.com/removeAttr/)\n * - [`removeClass()`](http://api.jquery.com/removeClass/)\n * - [`removeData()`](http://api.jquery.com/removeData/)\n * - [`replaceWith()`](http://api.jquery.com/replaceWith/)\n * - [`text()`](http://api.jquery.com/text/)\n * - [`toggleClass()`](http://api.jquery.com/toggleClass/)\n * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.\n * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces\n * - [`val()`](http://api.jquery.com/val/)\n * - [`wrap()`](http://api.jquery.com/wrap/)\n *\n * ## jQuery/jqLite Extras\n * Angular also provides the following additional methods and events to both jQuery and jqLite:\n *\n * ### Events\n * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event\n * on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM\n * element before it is removed.\n *\n * ### Methods\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n * retrieves controller associated with the `ngController` directive. If `name` is provided as\n * camelCase directive name, then the controller for this directive will be retrieved (e.g.\n * `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current\n * element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to\n * be enabled.\n * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the\n * current element. This getter should be used only on elements that contain a directive which starts a new isolate\n * scope. Calling `scope()` on this element always returns the original non-isolate scope.\n * Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n * parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nJQLite.expando = 'ng339';\n\nvar jqCache = JQLite.cache = {},\n jqId = 1,\n addEventListenerFn = function(element, type, fn) {\n element.addEventListener(type, fn, false);\n },\n removeEventListenerFn = function(element, type, fn) {\n element.removeEventListener(type, fn, false);\n };\n\n/*\n * !!! This is an undocumented \"private\" function !!!\n */\nJQLite._data = function(node) {\n //jQuery always returns an object on cache miss\n return this.cache[node[this.expando]] || {};\n};\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\nvar MOUSE_EVENT_MAP= { mouseleave: \"mouseout\", mouseenter: \"mouseover\"};\nvar jqLiteMinErr = minErr('jqLite');\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n return name.\n replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n return offset ? letter.toUpperCase() : letter;\n }).\n replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\nvar SINGLE_TAG_REGEXP = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/;\nvar HTML_REGEXP = /<|&#?\\w+;/;\nvar TAG_NAME_REGEXP = /<([\\w:]+)/;\nvar XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi;\n\nvar wrapMap = {\n 'option': [1, ''],\n\n 'thead': [1, '', '
'],\n 'col': [2, '', '
'],\n 'tr': [2, '', '
'],\n 'td': [3, '', '
'],\n '_default': [0, \"\", \"\"]\n};\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n\nfunction jqLiteIsTextNode(html) {\n return !HTML_REGEXP.test(html);\n}\n\nfunction jqLiteAcceptsData(node) {\n // The window object can accept data but has no nodeType\n // Otherwise we are only interested in elements (1) and documents (9)\n var nodeType = node.nodeType;\n return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;\n}\n\nfunction jqLiteBuildFragment(html, context) {\n var tmp, tag, wrap,\n fragment = context.createDocumentFragment(),\n nodes = [], i;\n\n if (jqLiteIsTextNode(html)) {\n // Convert non-html into a text node\n nodes.push(context.createTextNode(html));\n } else {\n // Convert html into DOM nodes\n tmp = tmp || fragment.appendChild(context.createElement(\"div\"));\n tag = (TAG_NAME_REGEXP.exec(html) || [\"\", \"\"])[1].toLowerCase();\n wrap = wrapMap[tag] || wrapMap._default;\n tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, \"<$1>\") + wrap[2];\n\n // Descend through wrappers to the right content\n i = wrap[0];\n while (i--) {\n tmp = tmp.lastChild;\n }\n\n nodes = concat(nodes, tmp.childNodes);\n\n tmp = fragment.firstChild;\n tmp.textContent = \"\";\n }\n\n // Remove wrapper from fragment\n fragment.textContent = \"\";\n fragment.innerHTML = \"\"; // Clear inner HTML\n forEach(nodes, function(node) {\n fragment.appendChild(node);\n });\n\n return fragment;\n}\n\nfunction jqLiteParseHTML(html, context) {\n context = context || document;\n var parsed;\n\n if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {\n return [context.createElement(parsed[1])];\n }\n\n if ((parsed = jqLiteBuildFragment(html, context))) {\n return parsed.childNodes;\n }\n\n return [];\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n if (element instanceof JQLite) {\n return element;\n }\n\n var argIsString;\n\n if (isString(element)) {\n element = trim(element);\n argIsString = true;\n }\n if (!(this instanceof JQLite)) {\n if (argIsString && element.charAt(0) != '<') {\n throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');\n }\n return new JQLite(element);\n }\n\n if (argIsString) {\n jqLiteAddNodes(this, jqLiteParseHTML(element));\n } else {\n jqLiteAddNodes(this, element);\n }\n}\n\nfunction jqLiteClone(element) {\n return element.cloneNode(true);\n}\n\nfunction jqLiteDealoc(element, onlyDescendants) {\n if (!onlyDescendants) jqLiteRemoveData(element);\n\n if (element.querySelectorAll) {\n var descendants = element.querySelectorAll('*');\n for (var i = 0, l = descendants.length; i < l; i++) {\n jqLiteRemoveData(descendants[i]);\n }\n }\n}\n\nfunction jqLiteOff(element, type, fn, unsupported) {\n if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');\n\n var expandoStore = jqLiteExpandoStore(element);\n var events = expandoStore && expandoStore.events;\n var handle = expandoStore && expandoStore.handle;\n\n if (!handle) return; //no listeners registered\n\n if (!type) {\n for (type in events) {\n if (type !== '$destroy') {\n removeEventListenerFn(element, type, handle);\n }\n delete events[type];\n }\n } else {\n forEach(type.split(' '), function(type) {\n if (isDefined(fn)) {\n var listenerFns = events[type];\n arrayRemove(listenerFns || [], fn);\n if (listenerFns && listenerFns.length > 0) {\n return;\n }\n }\n\n removeEventListenerFn(element, type, handle);\n delete events[type];\n });\n }\n}\n\nfunction jqLiteRemoveData(element, name) {\n var expandoId = element.ng339;\n var expandoStore = expandoId && jqCache[expandoId];\n\n if (expandoStore) {\n if (name) {\n delete expandoStore.data[name];\n return;\n }\n\n if (expandoStore.handle) {\n if (expandoStore.events.$destroy) {\n expandoStore.handle({}, '$destroy');\n }\n jqLiteOff(element);\n }\n delete jqCache[expandoId];\n element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it\n }\n}\n\n\nfunction jqLiteExpandoStore(element, createIfNecessary) {\n var expandoId = element.ng339,\n expandoStore = expandoId && jqCache[expandoId];\n\n if (createIfNecessary && !expandoStore) {\n element.ng339 = expandoId = jqNextId();\n expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined};\n }\n\n return expandoStore;\n}\n\n\nfunction jqLiteData(element, key, value) {\n if (jqLiteAcceptsData(element)) {\n\n var isSimpleSetter = isDefined(value);\n var isSimpleGetter = !isSimpleSetter && key && !isObject(key);\n var massGetter = !key;\n var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter);\n var data = expandoStore && expandoStore.data;\n\n if (isSimpleSetter) { // data('key', value)\n data[key] = value;\n } else {\n if (massGetter) { // data()\n return data;\n } else {\n if (isSimpleGetter) { // data('key')\n // don't force creation of expandoStore if it doesn't exist yet\n return data && data[key];\n } else { // mass-setter: data({key1: val1, key2: val2})\n extend(data, key);\n }\n }\n }\n }\n}\n\nfunction jqLiteHasClass(element, selector) {\n if (!element.getAttribute) return false;\n return ((\" \" + (element.getAttribute('class') || '') + \" \").replace(/[\\n\\t]/g, \" \").\n indexOf(\" \" + selector + \" \") > -1);\n}\n\nfunction jqLiteRemoveClass(element, cssClasses) {\n if (cssClasses && element.setAttribute) {\n forEach(cssClasses.split(' '), function(cssClass) {\n element.setAttribute('class', trim(\n (\" \" + (element.getAttribute('class') || '') + \" \")\n .replace(/[\\n\\t]/g, \" \")\n .replace(\" \" + trim(cssClass) + \" \", \" \"))\n );\n });\n }\n}\n\nfunction jqLiteAddClass(element, cssClasses) {\n if (cssClasses && element.setAttribute) {\n var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')\n .replace(/[\\n\\t]/g, \" \");\n\n forEach(cssClasses.split(' '), function(cssClass) {\n cssClass = trim(cssClass);\n if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {\n existingClasses += cssClass + ' ';\n }\n });\n\n element.setAttribute('class', trim(existingClasses));\n }\n}\n\n\nfunction jqLiteAddNodes(root, elements) {\n // THIS CODE IS VERY HOT. Don't make changes without benchmarking.\n\n if (elements) {\n\n // if a Node (the most common case)\n if (elements.nodeType) {\n root[root.length++] = elements;\n } else {\n var length = elements.length;\n\n // if an Array or NodeList and not a Window\n if (typeof length === 'number' && elements.window !== elements) {\n if (length) {\n for (var i = 0; i < length; i++) {\n root[root.length++] = elements[i];\n }\n }\n } else {\n root[root.length++] = elements;\n }\n }\n }\n}\n\n\nfunction jqLiteController(element, name) {\n return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller');\n}\n\nfunction jqLiteInheritedData(element, name, value) {\n // if element is the document object work with the html element instead\n // this makes $(document).scope() possible\n if (element.nodeType == NODE_TYPE_DOCUMENT) {\n element = element.documentElement;\n }\n var names = isArray(name) ? name : [name];\n\n while (element) {\n for (var i = 0, ii = names.length; i < ii; i++) {\n if ((value = jqLite.data(element, names[i])) !== undefined) return value;\n }\n\n // If dealing with a document fragment node with a host element, and no parent, use the host\n // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM\n // to lookup parent controllers.\n element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host);\n }\n}\n\nfunction jqLiteEmpty(element) {\n jqLiteDealoc(element, true);\n while (element.firstChild) {\n element.removeChild(element.firstChild);\n }\n}\n\nfunction jqLiteRemove(element, keepData) {\n if (!keepData) jqLiteDealoc(element);\n var parent = element.parentNode;\n if (parent) parent.removeChild(element);\n}\n\n\nfunction jqLiteDocumentLoaded(action, win) {\n win = win || window;\n if (win.document.readyState === 'complete') {\n // Force the action to be run async for consistent behaviour\n // from the action's point of view\n // i.e. it will definitely not be in a $apply\n win.setTimeout(action);\n } else {\n // No need to unbind this handler as load is only ever called once\n jqLite(win).on('load', action);\n }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n ready: function(fn) {\n var fired = false;\n\n function trigger() {\n if (fired) return;\n fired = true;\n fn();\n }\n\n // check if document is already loaded\n if (document.readyState === 'complete') {\n setTimeout(trigger);\n } else {\n this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9\n // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n // jshint -W064\n JQLite(window).on('load', trigger); // fallback to window.onload for others\n // jshint +W064\n }\n },\n toString: function() {\n var value = [];\n forEach(this, function(e) { value.push('' + e);});\n return '[' + value.join(', ') + ']';\n },\n\n eq: function(index) {\n return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n },\n\n length: 0,\n push: push,\n sort: [].sort,\n splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {\n BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form,details'.split(','), function(value) {\n BOOLEAN_ELEMENTS[value] = true;\n});\nvar ALIASED_ATTR = {\n 'ngMinlength': 'minlength',\n 'ngMaxlength': 'maxlength',\n 'ngMin': 'min',\n 'ngMax': 'max',\n 'ngPattern': 'pattern'\n};\n\nfunction getBooleanAttrName(element, name) {\n // check dom last since we will most likely fail on name\n var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n // booleanAttr is here twice to minimize DOM access\n return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;\n}\n\nfunction getAliasedAttrName(element, name) {\n var nodeName = element.nodeName;\n return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name];\n}\n\nforEach({\n data: jqLiteData,\n removeData: jqLiteRemoveData\n}, function(fn, name) {\n JQLite[name] = fn;\n});\n\nforEach({\n data: jqLiteData,\n inheritedData: jqLiteInheritedData,\n\n scope: function(element) {\n // Can't use jqLiteData here directly so we stay compatible with jQuery!\n return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);\n },\n\n isolateScope: function(element) {\n // Can't use jqLiteData here directly so we stay compatible with jQuery!\n return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');\n },\n\n controller: jqLiteController,\n\n injector: function(element) {\n return jqLiteInheritedData(element, '$injector');\n },\n\n removeAttr: function(element, name) {\n element.removeAttribute(name);\n },\n\n hasClass: jqLiteHasClass,\n\n css: function(element, name, value) {\n name = camelCase(name);\n\n if (isDefined(value)) {\n element.style[name] = value;\n } else {\n return element.style[name];\n }\n },\n\n attr: function(element, name, value) {\n var lowercasedName = lowercase(name);\n if (BOOLEAN_ATTR[lowercasedName]) {\n if (isDefined(value)) {\n if (!!value) {\n element[name] = true;\n element.setAttribute(name, lowercasedName);\n } else {\n element[name] = false;\n element.removeAttribute(lowercasedName);\n }\n } else {\n return (element[name] ||\n (element.attributes.getNamedItem(name) || noop).specified)\n ? lowercasedName\n : undefined;\n }\n } else if (isDefined(value)) {\n element.setAttribute(name, value);\n } else if (element.getAttribute) {\n // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n // some elements (e.g. Document) don't have get attribute, so return undefined\n var ret = element.getAttribute(name, 2);\n // normalize non-existing attributes to undefined (as jQuery)\n return ret === null ? undefined : ret;\n }\n },\n\n prop: function(element, name, value) {\n if (isDefined(value)) {\n element[name] = value;\n } else {\n return element[name];\n }\n },\n\n text: (function() {\n getText.$dv = '';\n return getText;\n\n function getText(element, value) {\n if (isUndefined(value)) {\n var nodeType = element.nodeType;\n return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : '';\n }\n element.textContent = value;\n }\n })(),\n\n val: function(element, value) {\n if (isUndefined(value)) {\n if (element.multiple && nodeName_(element) === 'select') {\n var result = [];\n forEach(element.options, function(option) {\n if (option.selected) {\n result.push(option.value || option.text);\n }\n });\n return result.length === 0 ? null : result;\n }\n return element.value;\n }\n element.value = value;\n },\n\n html: function(element, value) {\n if (isUndefined(value)) {\n return element.innerHTML;\n }\n jqLiteDealoc(element, true);\n element.innerHTML = value;\n },\n\n empty: jqLiteEmpty\n}, function(fn, name) {\n /**\n * Properties: writes return selection, reads return first value\n */\n JQLite.prototype[name] = function(arg1, arg2) {\n var i, key;\n var nodeCount = this.length;\n\n // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n // in a way that survives minification.\n // jqLiteEmpty takes no arguments but is a setter.\n if (fn !== jqLiteEmpty &&\n (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {\n if (isObject(arg1)) {\n\n // we are a write, but the object properties are the key/values\n for (i = 0; i < nodeCount; i++) {\n if (fn === jqLiteData) {\n // data() takes the whole object in jQuery\n fn(this[i], arg1);\n } else {\n for (key in arg1) {\n fn(this[i], key, arg1[key]);\n }\n }\n }\n // return self for chaining\n return this;\n } else {\n // we are a read, so read the first child.\n // TODO: do we still need this?\n var value = fn.$dv;\n // Only if we have $dv do we iterate over all, otherwise it is just the first element.\n var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;\n for (var j = 0; j < jj; j++) {\n var nodeValue = fn(this[j], arg1, arg2);\n value = value ? value + nodeValue : nodeValue;\n }\n return value;\n }\n } else {\n // we are a write, so apply to all children\n for (i = 0; i < nodeCount; i++) {\n fn(this[i], arg1, arg2);\n }\n // return self for chaining\n return this;\n }\n };\n});\n\nfunction createEventHandler(element, events) {\n var eventHandler = function(event, type) {\n // jQuery specific api\n event.isDefaultPrevented = function() {\n return event.defaultPrevented;\n };\n\n var eventFns = events[type || event.type];\n var eventFnsLength = eventFns ? eventFns.length : 0;\n\n if (!eventFnsLength) return;\n\n if (isUndefined(event.immediatePropagationStopped)) {\n var originalStopImmediatePropagation = event.stopImmediatePropagation;\n event.stopImmediatePropagation = function() {\n event.immediatePropagationStopped = true;\n\n if (event.stopPropagation) {\n event.stopPropagation();\n }\n\n if (originalStopImmediatePropagation) {\n originalStopImmediatePropagation.call(event);\n }\n };\n }\n\n event.isImmediatePropagationStopped = function() {\n return event.immediatePropagationStopped === true;\n };\n\n // Copy event handlers in case event handlers array is modified during execution.\n if ((eventFnsLength > 1)) {\n eventFns = shallowCopy(eventFns);\n }\n\n for (var i = 0; i < eventFnsLength; i++) {\n if (!event.isImmediatePropagationStopped()) {\n eventFns[i].call(element, event);\n }\n }\n };\n\n // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all\n // events on `element`\n eventHandler.elem = element;\n return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n removeData: jqLiteRemoveData,\n\n on: function jqLiteOn(element, type, fn, unsupported) {\n if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');\n\n // Do not add event handlers to non-elements because they will not be cleaned up.\n if (!jqLiteAcceptsData(element)) {\n return;\n }\n\n var expandoStore = jqLiteExpandoStore(element, true);\n var events = expandoStore.events;\n var handle = expandoStore.handle;\n\n if (!handle) {\n handle = expandoStore.handle = createEventHandler(element, events);\n }\n\n // http://jsperf.com/string-indexof-vs-split\n var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];\n var i = types.length;\n\n while (i--) {\n type = types[i];\n var eventFns = events[type];\n\n if (!eventFns) {\n events[type] = [];\n\n if (type === 'mouseenter' || type === 'mouseleave') {\n // Refer to jQuery's implementation of mouseenter & mouseleave\n // Read about mouseenter and mouseleave:\n // http://www.quirksmode.org/js/events_mouse.html#link8\n\n jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) {\n var target = this, related = event.relatedTarget;\n // For mousenter/leave call the handler if related is outside the target.\n // NB: No relatedTarget if the mouse left/entered the browser window\n if (!related || (related !== target && !target.contains(related))) {\n handle(event, type);\n }\n });\n\n } else {\n if (type !== '$destroy') {\n addEventListenerFn(element, type, handle);\n }\n }\n eventFns = events[type];\n }\n eventFns.push(fn);\n }\n },\n\n off: jqLiteOff,\n\n one: function(element, type, fn) {\n element = jqLite(element);\n\n //add the listener twice so that when it is called\n //you can remove the original function and still be\n //able to call element.off(ev, fn) normally\n element.on(type, function onFn() {\n element.off(type, fn);\n element.off(type, onFn);\n });\n element.on(type, fn);\n },\n\n replaceWith: function(element, replaceNode) {\n var index, parent = element.parentNode;\n jqLiteDealoc(element);\n forEach(new JQLite(replaceNode), function(node) {\n if (index) {\n parent.insertBefore(node, index.nextSibling);\n } else {\n parent.replaceChild(node, element);\n }\n index = node;\n });\n },\n\n children: function(element) {\n var children = [];\n forEach(element.childNodes, function(element) {\n if (element.nodeType === NODE_TYPE_ELEMENT)\n children.push(element);\n });\n return children;\n },\n\n contents: function(element) {\n return element.contentDocument || element.childNodes || [];\n },\n\n append: function(element, node) {\n var nodeType = element.nodeType;\n if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return;\n\n node = new JQLite(node);\n\n for (var i = 0, ii = node.length; i < ii; i++) {\n var child = node[i];\n element.appendChild(child);\n }\n },\n\n prepend: function(element, node) {\n if (element.nodeType === NODE_TYPE_ELEMENT) {\n var index = element.firstChild;\n forEach(new JQLite(node), function(child) {\n element.insertBefore(child, index);\n });\n }\n },\n\n wrap: function(element, wrapNode) {\n wrapNode = jqLite(wrapNode).eq(0).clone()[0];\n var parent = element.parentNode;\n if (parent) {\n parent.replaceChild(wrapNode, element);\n }\n wrapNode.appendChild(element);\n },\n\n remove: jqLiteRemove,\n\n detach: function(element) {\n jqLiteRemove(element, true);\n },\n\n after: function(element, newElement) {\n var index = element, parent = element.parentNode;\n newElement = new JQLite(newElement);\n\n for (var i = 0, ii = newElement.length; i < ii; i++) {\n var node = newElement[i];\n parent.insertBefore(node, index.nextSibling);\n index = node;\n }\n },\n\n addClass: jqLiteAddClass,\n removeClass: jqLiteRemoveClass,\n\n toggleClass: function(element, selector, condition) {\n if (selector) {\n forEach(selector.split(' '), function(className) {\n var classCondition = condition;\n if (isUndefined(classCondition)) {\n classCondition = !jqLiteHasClass(element, className);\n }\n (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);\n });\n }\n },\n\n parent: function(element) {\n var parent = element.parentNode;\n return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null;\n },\n\n next: function(element) {\n return element.nextElementSibling;\n },\n\n find: function(element, selector) {\n if (element.getElementsByTagName) {\n return element.getElementsByTagName(selector);\n } else {\n return [];\n }\n },\n\n clone: jqLiteClone,\n\n triggerHandler: function(element, event, extraParameters) {\n\n var dummyEvent, eventFnsCopy, handlerArgs;\n var eventName = event.type || event;\n var expandoStore = jqLiteExpandoStore(element);\n var events = expandoStore && expandoStore.events;\n var eventFns = events && events[eventName];\n\n if (eventFns) {\n // Create a dummy event to pass to the handlers\n dummyEvent = {\n preventDefault: function() { this.defaultPrevented = true; },\n isDefaultPrevented: function() { return this.defaultPrevented === true; },\n stopImmediatePropagation: function() { this.immediatePropagationStopped = true; },\n isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; },\n stopPropagation: noop,\n type: eventName,\n target: element\n };\n\n // If a custom event was provided then extend our dummy event with it\n if (event.type) {\n dummyEvent = extend(dummyEvent, event);\n }\n\n // Copy event handlers in case event handlers array is modified during execution.\n eventFnsCopy = shallowCopy(eventFns);\n handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];\n\n forEach(eventFnsCopy, function(fn) {\n if (!dummyEvent.isImmediatePropagationStopped()) {\n fn.apply(element, handlerArgs);\n }\n });\n }\n }\n}, function(fn, name) {\n /**\n * chaining functions\n */\n JQLite.prototype[name] = function(arg1, arg2, arg3) {\n var value;\n\n for (var i = 0, ii = this.length; i < ii; i++) {\n if (isUndefined(value)) {\n value = fn(this[i], arg1, arg2, arg3);\n if (isDefined(value)) {\n // any function which returns a value needs to be wrapped\n value = jqLite(value);\n }\n } else {\n jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));\n }\n }\n return isDefined(value) ? value : this;\n };\n\n // bind legacy bind/unbind to on/off\n JQLite.prototype.bind = JQLite.prototype.on;\n JQLite.prototype.unbind = JQLite.prototype.off;\n});\n\n\n// Provider for private $$jqLite service\nfunction $$jqLiteProvider() {\n this.$get = function $$jqLite() {\n return extend(JQLite, {\n hasClass: function(node, classes) {\n if (node.attr) node = node[0];\n return jqLiteHasClass(node, classes);\n },\n addClass: function(node, classes) {\n if (node.attr) node = node[0];\n return jqLiteAddClass(node, classes);\n },\n removeClass: function(node, classes) {\n if (node.attr) node = node[0];\n return jqLiteRemoveClass(node, classes);\n }\n });\n };\n}\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n * string is string\n * number is number as string\n * object is either result of calling $$hashKey function on the object or uniquely generated id,\n * that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n * The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj, nextUidFn) {\n var key = obj && obj.$$hashKey;\n\n if (key) {\n if (typeof key === 'function') {\n key = obj.$$hashKey();\n }\n return key;\n }\n\n var objType = typeof obj;\n if (objType == 'function' || (objType == 'object' && obj !== null)) {\n key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)();\n } else {\n key = objType + ':' + obj;\n }\n\n return key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array, isolatedUid) {\n if (isolatedUid) {\n var uid = 0;\n this.nextUid = function() {\n return ++uid;\n };\n }\n forEach(array, this.put, this);\n}\nHashMap.prototype = {\n /**\n * Store key value pair\n * @param key key to store can be any type\n * @param value value to store can be any type\n */\n put: function(key, value) {\n this[hashKey(key, this.nextUid)] = value;\n },\n\n /**\n * @param key\n * @returns {Object} the value for the key\n */\n get: function(key) {\n return this[hashKey(key, this.nextUid)];\n },\n\n /**\n * Remove the key/value pair\n * @param key\n */\n remove: function(key) {\n var value = this[key = hashKey(key, this.nextUid)];\n delete this[key];\n return value;\n }\n};\n\n/**\n * @ngdoc function\n * @module ng\n * @name angular.injector\n * @kind function\n *\n * @description\n * Creates an injector object that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n * @param {Array.} modules A list of module functions or their aliases. See\n * {@link angular.module}. The `ng` module must be explicitly added.\n * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which\n * disallows argument name annotation inference.\n * @returns {injector} Injector object. See {@link auto.$injector $injector}.\n *\n * @example\n * Typical usage\n * ```js\n * // create an injector\n * var $injector = angular.injector(['ng']);\n *\n * // use the injector to kick off your application\n * // use the type inference to auto inject arguments, or use implicit injection\n * $injector.invoke(function($rootScope, $compile, $document) {\n * $compile($document)($rootScope);\n * $rootScope.$digest();\n * });\n * ```\n *\n * Sometimes you want to get access to the injector of a currently running Angular app\n * from outside Angular. Perhaps, you want to inject and compile some markup after the\n * application has been bootstrapped. You can do this using the extra `injector()` added\n * to JQuery/jqLite elements. See {@link angular.element}.\n *\n * *This is fairly rare but could be the case if a third party library is injecting the\n * markup.*\n *\n * In the following example a new block of HTML containing a `ng-controller`\n * directive is added to the end of the document body by JQuery. We then compile and link\n * it into the current AngularJS scope.\n *\n * ```js\n * var $div = $('
{{content.label}}
');\n * $(document.body).append($div);\n *\n * angular.element(document).injector().invoke(function($compile) {\n * var scope = angular.element($div).scope();\n * $compile($div)(scope);\n * });\n * ```\n */\n\n\n/**\n * @ngdoc module\n * @name auto\n * @description\n *\n * Implicit module which gets automatically added to each {@link auto.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nvar $injectorMinErr = minErr('$injector');\n\nfunction anonFn(fn) {\n // For anonymous functions, showing at the very least the function signature can help in\n // debugging.\n var fnText = fn.toString().replace(STRIP_COMMENTS, ''),\n args = fnText.match(FN_ARGS);\n if (args) {\n return 'function(' + (args[1] || '').replace(/[\\s\\r\\n]+/, ' ') + ')';\n }\n return 'fn';\n}\n\nfunction annotate(fn, strictDi, name) {\n var $inject,\n fnText,\n argDecl,\n last;\n\n if (typeof fn === 'function') {\n if (!($inject = fn.$inject)) {\n $inject = [];\n if (fn.length) {\n if (strictDi) {\n if (!isString(name) || !name) {\n name = fn.name || anonFn(fn);\n }\n throw $injectorMinErr('strictdi',\n '{0} is not using explicit annotation and cannot be invoked in strict mode', name);\n }\n fnText = fn.toString().replace(STRIP_COMMENTS, '');\n argDecl = fnText.match(FN_ARGS);\n forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {\n arg.replace(FN_ARG, function(all, underscore, name) {\n $inject.push(name);\n });\n });\n }\n fn.$inject = $inject;\n }\n } else if (isArray(fn)) {\n last = fn.length - 1;\n assertArgFn(fn[last], 'fn');\n $inject = fn.slice(0, last);\n } else {\n assertArgFn(fn, 'fn', true);\n }\n return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc service\n * @name $injector\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link auto.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * ```js\n * var $injector = angular.injector();\n * expect($injector.get('$injector')).toBe($injector);\n * expect($injector.invoke(function($injector) {\n * return $injector;\n * })).toBe($injector);\n * ```\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following are all valid ways of annotating function with injection arguments and are equivalent.\n *\n * ```js\n * // inferred (only works if code not minified/obfuscated)\n * $injector.invoke(function(serviceA){});\n *\n * // annotated\n * function explicit(serviceA) {};\n * explicit.$inject = ['serviceA'];\n * $injector.invoke(explicit);\n *\n * // inline\n * $injector.invoke(['serviceA', function(serviceA){}]);\n * ```\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition\n * can then be parsed and the function arguments can be extracted. This method of discovering\n * annotations is disallowed when the injector is in strict mode.\n * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the\n * argument names.\n *\n * ## `$inject` Annotation\n * By adding an `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name $injector#get\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @param {string} caller An optional string to provide the origin of the function call for error messages.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name $injector#invoke\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!Function} fn The function to invoke. Function parameters are injected according to the\n * {@link guide/di $inject Annotation} rules.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this\n * object first, before the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name $injector#has\n *\n * @description\n * Allows the user to query if the particular service exists.\n *\n * @param {string} name Name of the service to query.\n * @returns {boolean} `true` if injector has given service.\n */\n\n/**\n * @ngdoc method\n * @name $injector#instantiate\n * @description\n * Create a new instance of JS type. The method takes a constructor function, invokes the new\n * operator, and supplies all of the arguments to the constructor function as specified by the\n * constructor annotation.\n *\n * @param {Function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this\n * object first, before the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name $injector#annotate\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is\n * used by the injector to determine which services need to be injected into the function when the\n * function is invoked. There are three ways in which the function can be annotated with the needed\n * dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done\n * by converting the function into a string using `toString()` method and extracting the argument\n * names.\n * ```js\n * // Given\n * function MyController($scope, $route) {\n * // ...\n * }\n *\n * // Then\n * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * ```\n *\n * You can disallow this method by using strict injection mode.\n *\n * This method does not work with code minification / obfuscation. For this reason the following\n * annotation strategies are supported.\n *\n * # The `$inject` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings\n * represent names of services to be injected into the function.\n * ```js\n * // Given\n * var MyController = function(obfuscatedScope, obfuscatedRoute) {\n * // ...\n * }\n * // Define function dependencies\n * MyController['$inject'] = ['$scope', '$route'];\n *\n * // Then\n * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * ```\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property\n * is very inconvenient. In these situations using the array notation to specify the dependencies in\n * a way that survives minification is a better choice:\n *\n * ```js\n * // We wish to write this (not minification / obfuscation safe)\n * injector.invoke(function($compile, $rootScope) {\n * // ...\n * });\n *\n * // We are forced to write break inlining\n * var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n * // ...\n * };\n * tmpFn.$inject = ['$compile', '$rootScope'];\n * injector.invoke(tmpFn);\n *\n * // To better support inline function the inline annotation is supported\n * injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n * // ...\n * }]);\n *\n * // Therefore\n * expect(injector.annotate(\n * ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n * ).toEqual(['$compile', '$rootScope']);\n * ```\n *\n * @param {Function|Array.} fn Function for which dependent service names need to\n * be retrieved as described above.\n *\n * @param {boolean=} [strictDi=false] Disallow argument name annotation inference.\n *\n * @returns {Array.} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc service\n * @name $provide\n *\n * @description\n *\n * The {@link auto.$provide $provide} service has a number of methods for registering components\n * with the {@link auto.$injector $injector}. Many of these functions are also exposed on\n * {@link angular.Module}.\n *\n * An Angular **service** is a singleton object created by a **service factory**. These **service\n * factories** are functions which, in turn, are created by a **service provider**.\n * The **service providers** are constructor functions. When instantiated they must contain a\n * property called `$get`, which holds the **service factory** function.\n *\n * When you request a service, the {@link auto.$injector $injector} is responsible for finding the\n * correct **service provider**, instantiating it and then calling its `$get` **service factory**\n * function to get the instance of the **service**.\n *\n * Often services have no configuration options and there is no need to add methods to the service\n * provider. The provider will be no more than a constructor function with a `$get` property. For\n * these cases the {@link auto.$provide $provide} service has additional helper methods to register\n * services without specifying a provider.\n *\n * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the\n * {@link auto.$injector $injector}\n * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by\n * providers and services.\n * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by\n * services, not providers.\n * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,\n * that will be wrapped in a **service provider** object, whose `$get` property will contain the\n * given factory function.\n * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`\n * that will be wrapped in a **service provider** object, whose `$get` property will instantiate\n * a new object using the given constructor function.\n *\n * See the individual methods for more information and examples.\n */\n\n/**\n * @ngdoc method\n * @name $provide#provider\n * @description\n *\n * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions\n * are constructor functions, whose instances are responsible for \"providing\" a factory for a\n * service.\n *\n * Service provider names start with the name of the service they provide followed by `Provider`.\n * For example, the {@link ng.$log $log} service has a provider called\n * {@link ng.$logProvider $logProvider}.\n *\n * Service provider objects can have additional methods which allow configuration of the provider\n * and its service. Importantly, you can configure what kind of service is created by the `$get`\n * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a\n * method {@link ng.$logProvider#debugEnabled debugEnabled}\n * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the\n * console or not.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name +\n 'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n * {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.\n * - `Constructor`: a new instance of the provider will be created using\n * {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n\n * @example\n *\n * The following example shows how to create a simple event tracking service and register it using\n * {@link auto.$provide#provider $provide.provider()}.\n *\n * ```js\n * // Define the eventTracker provider\n * function EventTrackerProvider() {\n * var trackingUrl = '/track';\n *\n * // A provider method for configuring where the tracked events should been saved\n * this.setTrackingUrl = function(url) {\n * trackingUrl = url;\n * };\n *\n * // The service factory function\n * this.$get = ['$http', function($http) {\n * var trackedEvents = {};\n * return {\n * // Call this to track an event\n * event: function(event) {\n * var count = trackedEvents[event] || 0;\n * count += 1;\n * trackedEvents[event] = count;\n * return count;\n * },\n * // Call this to save the tracked events to the trackingUrl\n * save: function() {\n * $http.post(trackingUrl, trackedEvents);\n * }\n * };\n * }];\n * }\n *\n * describe('eventTracker', function() {\n * var postSpy;\n *\n * beforeEach(module(function($provide) {\n * // Register the eventTracker provider\n * $provide.provider('eventTracker', EventTrackerProvider);\n * }));\n *\n * beforeEach(module(function(eventTrackerProvider) {\n * // Configure eventTracker provider\n * eventTrackerProvider.setTrackingUrl('/custom-track');\n * }));\n *\n * it('tracks events', inject(function(eventTracker) {\n * expect(eventTracker.event('login')).toEqual(1);\n * expect(eventTracker.event('login')).toEqual(2);\n * }));\n *\n * it('saves to the tracking url', inject(function(eventTracker, $http) {\n * postSpy = spyOn($http, 'post');\n * eventTracker.event('login');\n * eventTracker.save();\n * expect(postSpy).toHaveBeenCalled();\n * expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');\n * expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');\n * expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });\n * }));\n * });\n * ```\n */\n\n/**\n * @ngdoc method\n * @name $provide#factory\n * @description\n *\n * Register a **service factory**, which will be called to return the service instance.\n * This is short for registering a service where its provider consists of only a `$get` property,\n * which is the given service factory function.\n * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to\n * configure your service in a provider.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand\n * for `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here is an example of registering a service\n * ```js\n * $provide.factory('ping', ['$http', function($http) {\n * return function ping() {\n * return $http.send('/ping');\n * };\n * }]);\n * ```\n * You would then inject and use this service like this:\n * ```js\n * someModule.controller('Ctrl', ['ping', function(ping) {\n * ping();\n * }]);\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#service\n * @description\n *\n * Register a **service constructor**, which will be invoked with `new` to create the service\n * instance.\n * This is short for registering a service where its provider's `$get` property is the service\n * constructor function that will be used to instantiate the service instance.\n *\n * You should use {@link auto.$provide#service $provide.service(class)} if you define your service\n * as a type/class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here is an example of registering a service using\n * {@link auto.$provide#service $provide.service(class)}.\n * ```js\n * var Ping = function($http) {\n * this.$http = $http;\n * };\n *\n * Ping.$inject = ['$http'];\n *\n * Ping.prototype.send = function() {\n * return this.$http.get('/ping');\n * };\n * $provide.service('ping', Ping);\n * ```\n * You would then inject and use this service like this:\n * ```js\n * someModule.controller('Ctrl', ['ping', function(ping) {\n * ping.send();\n * }]);\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#value\n * @description\n *\n * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a\n * number, an array, an object or a function. This is short for registering a service where its\n * provider's `$get` property is a factory function that takes no arguments and returns the **value\n * service**.\n *\n * Value services are similar to constant services, except that they cannot be injected into a\n * module configuration function (see {@link angular.Module#config}) but they can be overridden by\n * an Angular\n * {@link auto.$provide#decorator decorator}.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here are some examples of creating value services.\n * ```js\n * $provide.value('ADMIN_USER', 'admin');\n *\n * $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });\n *\n * $provide.value('halfOf', function(value) {\n * return value / 2;\n * });\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#constant\n * @description\n *\n * Register a **constant service**, such as a string, a number, an array, an object or a function,\n * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be\n * injected into a module configuration function (see {@link angular.Module#config}) and it cannot\n * be overridden by an Angular {@link auto.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n *\n * @example\n * Here a some examples of creating constants:\n * ```js\n * $provide.constant('SHARD_HEIGHT', 306);\n *\n * $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);\n *\n * $provide.constant('double', function(value) {\n * return value * 2;\n * });\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#decorator\n * @description\n *\n * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator\n * intercepts the creation of a service, allowing it to override or modify the behaviour of the\n * service. The object returned by the decorator may be the original service, or a new service\n * object which replaces or wraps and delegates to the original service.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n * instantiated and should return the decorated service instance. The function is called using\n * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.\n * Local injection arguments:\n *\n * * `$delegate` - The original service instance, which can be monkey patched, configured,\n * decorated or delegated to.\n *\n * @example\n * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting\n * calls to {@link ng.$log#error $log.warn()}.\n * ```js\n * $provide.decorator('$log', ['$delegate', function($delegate) {\n * $delegate.warn = $delegate.error;\n * return $delegate;\n * }]);\n * ```\n */\n\n\nfunction createInjector(modulesToLoad, strictDi) {\n strictDi = (strictDi === true);\n var INSTANTIATING = {},\n providerSuffix = 'Provider',\n path = [],\n loadedModules = new HashMap([], true),\n providerCache = {\n $provide: {\n provider: supportObject(provider),\n factory: supportObject(factory),\n service: supportObject(service),\n value: supportObject(value),\n constant: supportObject(constant),\n decorator: decorator\n }\n },\n providerInjector = (providerCache.$injector =\n createInternalInjector(providerCache, function(serviceName, caller) {\n if (angular.isString(caller)) {\n path.push(caller);\n }\n throw $injectorMinErr('unpr', \"Unknown provider: {0}\", path.join(' <- '));\n })),\n instanceCache = {},\n instanceInjector = (instanceCache.$injector =\n createInternalInjector(instanceCache, function(serviceName, caller) {\n var provider = providerInjector.get(serviceName + providerSuffix, caller);\n return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);\n }));\n\n\n forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n return instanceInjector;\n\n ////////////////////////////////////\n // $provider\n ////////////////////////////////////\n\n function supportObject(delegate) {\n return function(key, value) {\n if (isObject(key)) {\n forEach(key, reverseParams(delegate));\n } else {\n return delegate(key, value);\n }\n };\n }\n\n function provider(name, provider_) {\n assertNotHasOwnProperty(name, 'service');\n if (isFunction(provider_) || isArray(provider_)) {\n provider_ = providerInjector.instantiate(provider_);\n }\n if (!provider_.$get) {\n throw $injectorMinErr('pget', \"Provider '{0}' must define $get factory method.\", name);\n }\n return providerCache[name + providerSuffix] = provider_;\n }\n\n function enforceReturnValue(name, factory) {\n return function enforcedReturnValue() {\n var result = instanceInjector.invoke(factory, this);\n if (isUndefined(result)) {\n throw $injectorMinErr('undef', \"Provider '{0}' must return a value from $get factory method.\", name);\n }\n return result;\n };\n }\n\n function factory(name, factoryFn, enforce) {\n return provider(name, {\n $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn\n });\n }\n\n function service(name, constructor) {\n return factory(name, ['$injector', function($injector) {\n return $injector.instantiate(constructor);\n }]);\n }\n\n function value(name, val) { return factory(name, valueFn(val), false); }\n\n function constant(name, value) {\n assertNotHasOwnProperty(name, 'constant');\n providerCache[name] = value;\n instanceCache[name] = value;\n }\n\n function decorator(serviceName, decorFn) {\n var origProvider = providerInjector.get(serviceName + providerSuffix),\n orig$get = origProvider.$get;\n\n origProvider.$get = function() {\n var origInstance = instanceInjector.invoke(orig$get, origProvider);\n return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n };\n }\n\n ////////////////////////////////////\n // Module Loading\n ////////////////////////////////////\n function loadModules(modulesToLoad) {\n var runBlocks = [], moduleFn;\n forEach(modulesToLoad, function(module) {\n if (loadedModules.get(module)) return;\n loadedModules.put(module, true);\n\n function runInvokeQueue(queue) {\n var i, ii;\n for (i = 0, ii = queue.length; i < ii; i++) {\n var invokeArgs = queue[i],\n provider = providerInjector.get(invokeArgs[0]);\n\n provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n }\n }\n\n try {\n if (isString(module)) {\n moduleFn = angularModule(module);\n runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n runInvokeQueue(moduleFn._invokeQueue);\n runInvokeQueue(moduleFn._configBlocks);\n } else if (isFunction(module)) {\n runBlocks.push(providerInjector.invoke(module));\n } else if (isArray(module)) {\n runBlocks.push(providerInjector.invoke(module));\n } else {\n assertArgFn(module, 'module');\n }\n } catch (e) {\n if (isArray(module)) {\n module = module[module.length - 1];\n }\n if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {\n // Safari & FF's stack traces don't contain error.message content\n // unlike those of Chrome and IE\n // So if stack doesn't contain message, we create a new string that contains both.\n // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.\n /* jshint -W022 */\n e = e.message + '\\n' + e.stack;\n }\n throw $injectorMinErr('modulerr', \"Failed to instantiate module {0} due to:\\n{1}\",\n module, e.stack || e.message || e);\n }\n });\n return runBlocks;\n }\n\n ////////////////////////////////////\n // internal Injector\n ////////////////////////////////////\n\n function createInternalInjector(cache, factory) {\n\n function getService(serviceName, caller) {\n if (cache.hasOwnProperty(serviceName)) {\n if (cache[serviceName] === INSTANTIATING) {\n throw $injectorMinErr('cdep', 'Circular dependency found: {0}',\n serviceName + ' <- ' + path.join(' <- '));\n }\n return cache[serviceName];\n } else {\n try {\n path.unshift(serviceName);\n cache[serviceName] = INSTANTIATING;\n return cache[serviceName] = factory(serviceName, caller);\n } catch (err) {\n if (cache[serviceName] === INSTANTIATING) {\n delete cache[serviceName];\n }\n throw err;\n } finally {\n path.shift();\n }\n }\n }\n\n function invoke(fn, self, locals, serviceName) {\n if (typeof locals === 'string') {\n serviceName = locals;\n locals = null;\n }\n\n var args = [],\n $inject = annotate(fn, strictDi, serviceName),\n length, i,\n key;\n\n for (i = 0, length = $inject.length; i < length; i++) {\n key = $inject[i];\n if (typeof key !== 'string') {\n throw $injectorMinErr('itkn',\n 'Incorrect injection token! Expected service name as string, got {0}', key);\n }\n args.push(\n locals && locals.hasOwnProperty(key)\n ? locals[key]\n : getService(key, serviceName)\n );\n }\n if (isArray(fn)) {\n fn = fn[length];\n }\n\n // http://jsperf.com/angularjs-invoke-apply-vs-switch\n // #5388\n return fn.apply(self, args);\n }\n\n function instantiate(Type, locals, serviceName) {\n // Check if Type is annotated and use just the given function at n-1 as parameter\n // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);\n // Object creation: http://jsperf.com/create-constructor/2\n var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null);\n var returnedValue = invoke(Type, instance, locals, serviceName);\n\n return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;\n }\n\n return {\n invoke: invoke,\n instantiate: instantiate,\n get: getService,\n annotate: annotate,\n has: function(name) {\n return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);\n }\n };\n }\n}\n\ncreateInjector.$$annotate = annotate;\n\n/**\n * @ngdoc provider\n * @name $anchorScrollProvider\n *\n * @description\n * Use `$anchorScrollProvider` to disable automatic scrolling whenever\n * {@link ng.$location#hash $location.hash()} changes.\n */\nfunction $AnchorScrollProvider() {\n\n var autoScrollingEnabled = true;\n\n /**\n * @ngdoc method\n * @name $anchorScrollProvider#disableAutoScrolling\n *\n * @description\n * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to\n * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.
\n * Use this method to disable automatic scrolling.\n *\n * If automatic scrolling is disabled, one must explicitly call\n * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the\n * current hash.\n */\n this.disableAutoScrolling = function() {\n autoScrollingEnabled = false;\n };\n\n /**\n * @ngdoc service\n * @name $anchorScroll\n * @kind function\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks the current value of {@link ng.$location#hash $location.hash()} and\n * scrolls to the related element, according to the rules specified in the\n * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).\n *\n * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to\n * match any anchor whenever it changes. This can be disabled by calling\n * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}.\n *\n * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a\n * vertical scroll-offset (either fixed or dynamic).\n *\n * @property {(number|function|jqLite)} yOffset\n * If set, specifies a vertical scroll-offset. This is often useful when there are fixed\n * positioned elements at the top of the page, such as navbars, headers etc.\n *\n * `yOffset` can be specified in various ways:\n * - **number**: A fixed number of pixels to be used as offset.

\n * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return\n * a number representing the offset (in pixels).

\n * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from\n * the top of the page to the element's bottom will be used as offset.
\n * **Note**: The element will be taken into account only as long as its `position` is set to\n * `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust\n * their height and/or positioning according to the viewport's size.\n *\n *
\n *
\n * In order for `yOffset` to work properly, scrolling should take place on the document's root and\n * not some child element.\n *
\n *\n * @example\n \n \n
\n Go to bottom\n You're at the bottom!\n
\n
\n \n angular.module('anchorScrollExample', [])\n .controller('ScrollController', ['$scope', '$location', '$anchorScroll',\n function ($scope, $location, $anchorScroll) {\n $scope.gotoBottom = function() {\n // set the location.hash to the id of\n // the element you wish to scroll to.\n $location.hash('bottom');\n\n // call $anchorScroll()\n $anchorScroll();\n };\n }]);\n \n \n #scrollArea {\n height: 280px;\n overflow: auto;\n }\n\n #bottom {\n display: block;\n margin-top: 2000px;\n }\n \n
\n *\n *
\n * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value).\n * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details.\n *\n * @example\n \n \n \n
\n Anchor {{x}} of 5\n
\n
\n \n angular.module('anchorScrollOffsetExample', [])\n .run(['$anchorScroll', function($anchorScroll) {\n $anchorScroll.yOffset = 50; // always scroll by 50 extra pixels\n }])\n .controller('headerCtrl', ['$anchorScroll', '$location', '$scope',\n function ($anchorScroll, $location, $scope) {\n $scope.gotoAnchor = function(x) {\n var newHash = 'anchor' + x;\n if ($location.hash() !== newHash) {\n // set the $location.hash to `newHash` and\n // $anchorScroll will automatically scroll to it\n $location.hash('anchor' + x);\n } else {\n // call $anchorScroll() explicitly,\n // since $location.hash hasn't changed\n $anchorScroll();\n }\n };\n }\n ]);\n \n \n body {\n padding-top: 50px;\n }\n\n .anchor {\n border: 2px dashed DarkOrchid;\n padding: 10px 10px 200px 10px;\n }\n\n .fixed-header {\n background-color: rgba(0, 0, 0, 0.2);\n height: 50px;\n position: fixed;\n top: 0; left: 0; right: 0;\n }\n\n .fixed-header > a {\n display: inline-block;\n margin: 5px 15px;\n }\n \n
\n */\n this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n var document = $window.document;\n\n // Helper function to get first anchor from a NodeList\n // (using `Array#some()` instead of `angular#forEach()` since it's more performant\n // and working in all supported browsers.)\n function getFirstAnchor(list) {\n var result = null;\n Array.prototype.some.call(list, function(element) {\n if (nodeName_(element) === 'a') {\n result = element;\n return true;\n }\n });\n return result;\n }\n\n function getYOffset() {\n\n var offset = scroll.yOffset;\n\n if (isFunction(offset)) {\n offset = offset();\n } else if (isElement(offset)) {\n var elem = offset[0];\n var style = $window.getComputedStyle(elem);\n if (style.position !== 'fixed') {\n offset = 0;\n } else {\n offset = elem.getBoundingClientRect().bottom;\n }\n } else if (!isNumber(offset)) {\n offset = 0;\n }\n\n return offset;\n }\n\n function scrollTo(elem) {\n if (elem) {\n elem.scrollIntoView();\n\n var offset = getYOffset();\n\n if (offset) {\n // `offset` is the number of pixels we should scroll UP in order to align `elem` properly.\n // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the\n // top of the viewport.\n //\n // IF the number of pixels from the top of `elem` to the end of the page's content is less\n // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some\n // way down the page.\n //\n // This is often the case for elements near the bottom of the page.\n //\n // In such cases we do not need to scroll the whole `offset` up, just the difference between\n // the top of the element and the offset, which is enough to align the top of `elem` at the\n // desired position.\n var elemTop = elem.getBoundingClientRect().top;\n $window.scrollBy(0, elemTop - offset);\n }\n } else {\n $window.scrollTo(0, 0);\n }\n }\n\n function scroll() {\n var hash = $location.hash(), elm;\n\n // empty hash, scroll to the top of the page\n if (!hash) scrollTo(null);\n\n // element with given id\n else if ((elm = document.getElementById(hash))) scrollTo(elm);\n\n // first anchor with given name :-D\n else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm);\n\n // no element and hash == 'top', scroll to the top of the page\n else if (hash === 'top') scrollTo(null);\n }\n\n // does not scroll when user clicks on anchor link that is currently on\n // (no url change, no $location.hash() change), browser native does scroll\n if (autoScrollingEnabled) {\n $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n function autoScrollWatchAction(newVal, oldVal) {\n // skip the initial scroll if $location.hash is empty\n if (newVal === oldVal && newVal === '') return;\n\n jqLiteDocumentLoaded(function() {\n $rootScope.$evalAsync(scroll);\n });\n });\n }\n\n return scroll;\n }];\n}\n\nvar $animateMinErr = minErr('$animate');\n\n/**\n * @ngdoc provider\n * @name $animateProvider\n *\n * @description\n * Default implementation of $animate that doesn't perform any animations, instead just\n * synchronously performs DOM\n * updates and calls done() callbacks.\n *\n * In order to enable animations the ngAnimate module has to be loaded.\n *\n * To see the functional implementation check out src/ngAnimate/animate.js\n */\nvar $AnimateProvider = ['$provide', function($provide) {\n\n\n this.$$selectors = {};\n\n\n /**\n * @ngdoc method\n * @name $animateProvider#register\n *\n * @description\n * Registers a new injectable animation factory function. The factory function produces the\n * animation object which contains callback functions for each event that is expected to be\n * animated.\n *\n * * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction`\n * must be called once the element animation is complete. If a function is returned then the\n * animation service will use this function to cancel the animation whenever a cancel event is\n * triggered.\n *\n *\n * ```js\n * return {\n * eventFn : function(element, done) {\n * //code to run the animation\n * //once complete, then run done()\n * return function cancellationFunction() {\n * //code to cancel the animation\n * }\n * }\n * }\n * ```\n *\n * @param {string} name The name of the animation.\n * @param {Function} factory The factory function that will be executed to return the animation\n * object.\n */\n this.register = function(name, factory) {\n var key = name + '-animation';\n if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel',\n \"Expecting class selector starting with '.' got '{0}'.\", name);\n this.$$selectors[name.substr(1)] = key;\n $provide.factory(key, factory);\n };\n\n /**\n * @ngdoc method\n * @name $animateProvider#classNameFilter\n *\n * @description\n * Sets and/or returns the CSS class regular expression that is checked when performing\n * an animation. Upon bootstrap the classNameFilter value is not set at all and will\n * therefore enable $animate to attempt to perform an animation on any element.\n * When setting the classNameFilter value, animations will only be performed on elements\n * that successfully match the filter expression. This in turn can boost performance\n * for low-powered devices as well as applications containing a lot of structural operations.\n * @param {RegExp=} expression The className expression which will be checked against all animations\n * @return {RegExp} The current CSS className expression value. If null then there is no expression value\n */\n this.classNameFilter = function(expression) {\n if (arguments.length === 1) {\n this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;\n }\n return this.$$classNameFilter;\n };\n\n this.$get = ['$$q', '$$asyncCallback', '$rootScope', function($$q, $$asyncCallback, $rootScope) {\n\n var currentDefer;\n\n function runAnimationPostDigest(fn) {\n var cancelFn, defer = $$q.defer();\n defer.promise.$$cancelFn = function ngAnimateMaybeCancel() {\n cancelFn && cancelFn();\n };\n\n $rootScope.$$postDigest(function ngAnimatePostDigest() {\n cancelFn = fn(function ngAnimateNotifyComplete() {\n defer.resolve();\n });\n });\n\n return defer.promise;\n }\n\n function resolveElementClasses(element, classes) {\n var toAdd = [], toRemove = [];\n\n var hasClasses = createMap();\n forEach((element.attr('class') || '').split(/\\s+/), function(className) {\n hasClasses[className] = true;\n });\n\n forEach(classes, function(status, className) {\n var hasClass = hasClasses[className];\n\n // If the most recent class manipulation (via $animate) was to remove the class, and the\n // element currently has the class, the class is scheduled for removal. Otherwise, if\n // the most recent class manipulation (via $animate) was to add the class, and the\n // element does not currently have the class, the class is scheduled to be added.\n if (status === false && hasClass) {\n toRemove.push(className);\n } else if (status === true && !hasClass) {\n toAdd.push(className);\n }\n });\n\n return (toAdd.length + toRemove.length) > 0 &&\n [toAdd.length ? toAdd : null, toRemove.length ? toRemove : null];\n }\n\n function cachedClassManipulation(cache, classes, op) {\n for (var i=0, ii = classes.length; i < ii; ++i) {\n var className = classes[i];\n cache[className] = op;\n }\n }\n\n function asyncPromise() {\n // only serve one instance of a promise in order to save CPU cycles\n if (!currentDefer) {\n currentDefer = $$q.defer();\n $$asyncCallback(function() {\n currentDefer.resolve();\n currentDefer = null;\n });\n }\n return currentDefer.promise;\n }\n\n function applyStyles(element, options) {\n if (angular.isObject(options)) {\n var styles = extend(options.from || {}, options.to || {});\n element.css(styles);\n }\n }\n\n /**\n *\n * @ngdoc service\n * @name $animate\n * @description The $animate service provides rudimentary DOM manipulation functions to\n * insert, remove and move elements within the DOM, as well as adding and removing classes.\n * This service is the core service used by the ngAnimate $animator service which provides\n * high-level animation hooks for CSS and JavaScript.\n *\n * $animate is available in the AngularJS core, however, the ngAnimate module must be included\n * to enable full out animation support. Otherwise, $animate will only perform simple DOM\n * manipulation operations.\n *\n * To learn more about enabling animation support, click here to visit the {@link ngAnimate\n * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service\n * page}.\n */\n return {\n animate: function(element, from, to) {\n applyStyles(element, { from: from, to: to });\n return asyncPromise();\n },\n\n /**\n *\n * @ngdoc method\n * @name $animate#enter\n * @kind function\n * @description Inserts the element into the DOM either after the `after` element or\n * as the first child within the `parent` element. When the function is called a promise\n * is returned that will be resolved at a later time.\n * @param {DOMElement} element the element which will be inserted into the DOM\n * @param {DOMElement} parent the parent element which will append the element as\n * a child (if the after element is not present)\n * @param {DOMElement} after the sibling element which will append the element\n * after itself\n * @param {object=} options an optional collection of styles that will be applied to the element.\n * @return {Promise} the animation callback promise\n */\n enter: function(element, parent, after, options) {\n applyStyles(element, options);\n after ? after.after(element)\n : parent.prepend(element);\n return asyncPromise();\n },\n\n /**\n *\n * @ngdoc method\n * @name $animate#leave\n * @kind function\n * @description Removes the element from the DOM. When the function is called a promise\n * is returned that will be resolved at a later time.\n * @param {DOMElement} element the element which will be removed from the DOM\n * @param {object=} options an optional collection of options that will be applied to the element.\n * @return {Promise} the animation callback promise\n */\n leave: function(element, options) {\n element.remove();\n return asyncPromise();\n },\n\n /**\n *\n * @ngdoc method\n * @name $animate#move\n * @kind function\n * @description Moves the position of the provided element within the DOM to be placed\n * either after the `after` element or inside of the `parent` element. When the function\n * is called a promise is returned that will be resolved at a later time.\n *\n * @param {DOMElement} element the element which will be moved around within the\n * DOM\n * @param {DOMElement} parent the parent element where the element will be\n * inserted into (if the after element is not present)\n * @param {DOMElement} after the sibling element where the element will be\n * positioned next to\n * @param {object=} options an optional collection of options that will be applied to the element.\n * @return {Promise} the animation callback promise\n */\n move: function(element, parent, after, options) {\n // Do not remove element before insert. Removing will cause data associated with the\n // element to be dropped. Insert will implicitly do the remove.\n return this.enter(element, parent, after, options);\n },\n\n /**\n *\n * @ngdoc method\n * @name $animate#addClass\n * @kind function\n * @description Adds the provided className CSS class value to the provided element.\n * When the function is called a promise is returned that will be resolved at a later time.\n * @param {DOMElement} element the element which will have the className value\n * added to it\n * @param {string} className the CSS class which will be added to the element\n * @param {object=} options an optional collection of options that will be applied to the element.\n * @return {Promise} the animation callback promise\n */\n addClass: function(element, className, options) {\n return this.setClass(element, className, [], options);\n },\n\n $$addClassImmediately: function(element, className, options) {\n element = jqLite(element);\n className = !isString(className)\n ? (isArray(className) ? className.join(' ') : '')\n : className;\n forEach(element, function(element) {\n jqLiteAddClass(element, className);\n });\n applyStyles(element, options);\n return asyncPromise();\n },\n\n /**\n *\n * @ngdoc method\n * @name $animate#removeClass\n * @kind function\n * @description Removes the provided className CSS class value from the provided element.\n * When the function is called a promise is returned that will be resolved at a later time.\n * @param {DOMElement} element the element which will have the className value\n * removed from it\n * @param {string} className the CSS class which will be removed from the element\n * @param {object=} options an optional collection of options that will be applied to the element.\n * @return {Promise} the animation callback promise\n */\n removeClass: function(element, className, options) {\n return this.setClass(element, [], className, options);\n },\n\n $$removeClassImmediately: function(element, className, options) {\n element = jqLite(element);\n className = !isString(className)\n ? (isArray(className) ? className.join(' ') : '')\n : className;\n forEach(element, function(element) {\n jqLiteRemoveClass(element, className);\n });\n applyStyles(element, options);\n return asyncPromise();\n },\n\n /**\n *\n * @ngdoc method\n * @name $animate#setClass\n * @kind function\n * @description Adds and/or removes the given CSS classes to and from the element.\n * When the function is called a promise is returned that will be resolved at a later time.\n * @param {DOMElement} element the element which will have its CSS classes changed\n * removed from it\n * @param {string} add the CSS classes which will be added to the element\n * @param {string} remove the CSS class which will be removed from the element\n * @param {object=} options an optional collection of options that will be applied to the element.\n * @return {Promise} the animation callback promise\n */\n setClass: function(element, add, remove, options) {\n var self = this;\n var STORAGE_KEY = '$$animateClasses';\n var createdCache = false;\n element = jqLite(element);\n\n var cache = element.data(STORAGE_KEY);\n if (!cache) {\n cache = {\n classes: {},\n options: options\n };\n createdCache = true;\n } else if (options && cache.options) {\n cache.options = angular.extend(cache.options || {}, options);\n }\n\n var classes = cache.classes;\n\n add = isArray(add) ? add : add.split(' ');\n remove = isArray(remove) ? remove : remove.split(' ');\n cachedClassManipulation(classes, add, true);\n cachedClassManipulation(classes, remove, false);\n\n if (createdCache) {\n cache.promise = runAnimationPostDigest(function(done) {\n var cache = element.data(STORAGE_KEY);\n element.removeData(STORAGE_KEY);\n\n // in the event that the element is removed before postDigest\n // is run then the cache will be undefined and there will be\n // no need anymore to add or remove and of the element classes\n if (cache) {\n var classes = resolveElementClasses(element, cache.classes);\n if (classes) {\n self.$$setClassImmediately(element, classes[0], classes[1], cache.options);\n }\n }\n\n done();\n });\n element.data(STORAGE_KEY, cache);\n }\n\n return cache.promise;\n },\n\n $$setClassImmediately: function(element, add, remove, options) {\n add && this.$$addClassImmediately(element, add);\n remove && this.$$removeClassImmediately(element, remove);\n applyStyles(element, options);\n return asyncPromise();\n },\n\n enabled: noop,\n cancel: noop\n };\n }];\n}];\n\nfunction $$AsyncCallbackProvider() {\n this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {\n return $$rAF.supported\n ? function(fn) { return $$rAF(fn); }\n : function(fn) {\n return $timeout(fn, 0, false);\n };\n }];\n}\n\n/* global stripHash: true */\n\n/**\n * ! This is a private undocumented service !\n *\n * @name $browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {object} $log window.console or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n var self = this,\n rawDocument = document[0],\n location = window.location,\n history = window.history,\n setTimeout = window.setTimeout,\n clearTimeout = window.clearTimeout,\n pendingDeferIds = {};\n\n self.isMock = false;\n\n var outstandingRequestCount = 0;\n var outstandingRequestCallbacks = [];\n\n // TODO(vojta): remove this temporary api\n self.$$completeOutstandingRequest = completeOutstandingRequest;\n self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n /**\n * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n */\n function completeOutstandingRequest(fn) {\n try {\n fn.apply(null, sliceArgs(arguments, 1));\n } finally {\n outstandingRequestCount--;\n if (outstandingRequestCount === 0) {\n while (outstandingRequestCallbacks.length) {\n try {\n outstandingRequestCallbacks.pop()();\n } catch (e) {\n $log.error(e);\n }\n }\n }\n }\n }\n\n function getHash(url) {\n var index = url.indexOf('#');\n return index === -1 ? '' : url.substr(index + 1);\n }\n\n /**\n * @private\n * Note: this method is used only by scenario runner\n * TODO(vojta): prefix this method with $$ ?\n * @param {function()} callback Function that will be called when no outstanding request\n */\n self.notifyWhenNoOutstandingRequests = function(callback) {\n // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n // regular poller would result in flaky tests.\n forEach(pollFns, function(pollFn) { pollFn(); });\n\n if (outstandingRequestCount === 0) {\n callback();\n } else {\n outstandingRequestCallbacks.push(callback);\n }\n };\n\n //////////////////////////////////////////////////////////////\n // Poll Watcher API\n //////////////////////////////////////////////////////////////\n var pollFns = [],\n pollTimeout;\n\n /**\n * @name $browser#addPollFn\n *\n * @param {function()} fn Poll function to add\n *\n * @description\n * Adds a function to the list of functions that poller periodically executes,\n * and starts polling if not started yet.\n *\n * @returns {function()} the added function\n */\n self.addPollFn = function(fn) {\n if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n pollFns.push(fn);\n return fn;\n };\n\n /**\n * @param {number} interval How often should browser call poll functions (ms)\n * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n *\n * @description\n * Configures the poller to run in the specified intervals, using the specified\n * setTimeout fn and kicks it off.\n */\n function startPoller(interval, setTimeout) {\n (function check() {\n forEach(pollFns, function(pollFn) { pollFn(); });\n pollTimeout = setTimeout(check, interval);\n })();\n }\n\n //////////////////////////////////////////////////////////////\n // URL API\n //////////////////////////////////////////////////////////////\n\n var cachedState, lastHistoryState,\n lastBrowserUrl = location.href,\n baseElement = document.find('base'),\n reloadLocation = null;\n\n cacheState();\n lastHistoryState = cachedState;\n\n /**\n * @name $browser#url\n *\n * @description\n * GETTER:\n * Without any argument, this method just returns current value of location.href.\n *\n * SETTER:\n * With at least one argument, this method sets url to new value.\n * If html5 history api supported, pushState/replaceState is used, otherwise\n * location.href/location.replace is used.\n * Returns its own instance to allow chaining\n *\n * NOTE: this api is intended for use only by the $location service. Please use the\n * {@link ng.$location $location service} to change url.\n *\n * @param {string} url New url (when used as setter)\n * @param {boolean=} replace Should new url replace current history record?\n * @param {object=} state object to use with pushState/replaceState\n */\n self.url = function(url, replace, state) {\n // In modern browsers `history.state` is `null` by default; treating it separately\n // from `undefined` would cause `$browser.url('/foo')` to change `history.state`\n // to undefined via `pushState`. Instead, let's change `undefined` to `null` here.\n if (isUndefined(state)) {\n state = null;\n }\n\n // Android Browser BFCache causes location, history reference to become stale.\n if (location !== window.location) location = window.location;\n if (history !== window.history) history = window.history;\n\n // setter\n if (url) {\n var sameState = lastHistoryState === state;\n\n // Don't change anything if previous and current URLs and states match. This also prevents\n // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode.\n // See https://github.com/angular/angular.js/commit/ffb2701\n if (lastBrowserUrl === url && (!$sniffer.history || sameState)) {\n return self;\n }\n var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);\n lastBrowserUrl = url;\n lastHistoryState = state;\n // Don't use history API if only the hash changed\n // due to a bug in IE10/IE11 which leads\n // to not firing a `hashchange` nor `popstate` event\n // in some cases (see #9143).\n if ($sniffer.history && (!sameBase || !sameState)) {\n history[replace ? 'replaceState' : 'pushState'](state, '', url);\n cacheState();\n // Do the assignment again so that those two variables are referentially identical.\n lastHistoryState = cachedState;\n } else {\n if (!sameBase) {\n reloadLocation = url;\n }\n if (replace) {\n location.replace(url);\n } else if (!sameBase) {\n location.href = url;\n } else {\n location.hash = getHash(url);\n }\n }\n return self;\n // getter\n } else {\n // - reloadLocation is needed as browsers don't allow to read out\n // the new location.href if a reload happened.\n // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n return reloadLocation || location.href.replace(/%27/g,\"'\");\n }\n };\n\n /**\n * @name $browser#state\n *\n * @description\n * This method is a getter.\n *\n * Return history.state or null if history.state is undefined.\n *\n * @returns {object} state\n */\n self.state = function() {\n return cachedState;\n };\n\n var urlChangeListeners = [],\n urlChangeInit = false;\n\n function cacheStateAndFireUrlChange() {\n cacheState();\n fireUrlChange();\n }\n\n // This variable should be used *only* inside the cacheState function.\n var lastCachedState = null;\n function cacheState() {\n // This should be the only place in $browser where `history.state` is read.\n cachedState = window.history.state;\n cachedState = isUndefined(cachedState) ? null : cachedState;\n\n // Prevent callbacks fo fire twice if both hashchange & popstate were fired.\n if (equals(cachedState, lastCachedState)) {\n cachedState = lastCachedState;\n }\n lastCachedState = cachedState;\n }\n\n function fireUrlChange() {\n if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) {\n return;\n }\n\n lastBrowserUrl = self.url();\n lastHistoryState = cachedState;\n forEach(urlChangeListeners, function(listener) {\n listener(self.url(), cachedState);\n });\n }\n\n /**\n * @name $browser#onUrlChange\n *\n * @description\n * Register callback function that will be called, when url changes.\n *\n * It's only called when the url is changed from outside of angular:\n * - user types different url into address bar\n * - user clicks on history (forward/back) button\n * - user clicks on a link\n *\n * It's not called when url is changed by $browser.url() method\n *\n * The listener gets called with new url as parameter.\n *\n * NOTE: this api is intended for use only by the $location service. Please use the\n * {@link ng.$location $location service} to monitor url changes in angular apps.\n *\n * @param {function(string)} listener Listener function to be called when url changes.\n * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n */\n self.onUrlChange = function(callback) {\n // TODO(vojta): refactor to use node's syntax for events\n if (!urlChangeInit) {\n // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n // don't fire popstate when user change the address bar and don't fire hashchange when url\n // changed by push/replaceState\n\n // html5 history api - popstate event\n if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange);\n // hashchange event\n jqLite(window).on('hashchange', cacheStateAndFireUrlChange);\n\n urlChangeInit = true;\n }\n\n urlChangeListeners.push(callback);\n return callback;\n };\n\n /**\n * Checks whether the url has changed outside of Angular.\n * Needs to be exported to be able to check for changes that have been done in sync,\n * as hashchange/popstate events fire in async.\n */\n self.$$checkUrlChange = fireUrlChange;\n\n //////////////////////////////////////////////////////////////\n // Misc API\n //////////////////////////////////////////////////////////////\n\n /**\n * @name $browser#baseHref\n *\n * @description\n * Returns current \n * (always relative - without domain)\n *\n * @returns {string} The current base href\n */\n self.baseHref = function() {\n var href = baseElement.attr('href');\n return href ? href.replace(/^(https?\\:)?\\/\\/[^\\/]*/, '') : '';\n };\n\n //////////////////////////////////////////////////////////////\n // Cookies API\n //////////////////////////////////////////////////////////////\n var lastCookies = {};\n var lastCookieString = '';\n var cookiePath = self.baseHref();\n\n function safeDecodeURIComponent(str) {\n try {\n return decodeURIComponent(str);\n } catch (e) {\n return str;\n }\n }\n\n /**\n * @name $browser#cookies\n *\n * @param {string=} name Cookie name\n * @param {string=} value Cookie value\n *\n * @description\n * The cookies method provides a 'private' low level access to browser cookies.\n * It is not meant to be used directly, use the $cookie service instead.\n *\n * The return values vary depending on the arguments that the method was called with as follows:\n *\n * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify\n * it\n * - cookies(name, value) -> set name to value, if value is undefined delete the cookie\n * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that\n * way)\n *\n * @returns {Object} Hash of all cookies (if called without any parameter)\n */\n self.cookies = function(name, value) {\n var cookieLength, cookieArray, cookie, i, index;\n\n if (name) {\n if (value === undefined) {\n rawDocument.cookie = encodeURIComponent(name) + \"=;path=\" + cookiePath +\n \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n } else {\n if (isString(value)) {\n cookieLength = (rawDocument.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) +\n ';path=' + cookiePath).length + 1;\n\n // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n // - 300 cookies\n // - 20 cookies per unique domain\n // - 4096 bytes per cookie\n if (cookieLength > 4096) {\n $log.warn(\"Cookie '\" + name +\n \"' possibly not set or overflowed because it was too large (\" +\n cookieLength + \" > 4096 bytes)!\");\n }\n }\n }\n } else {\n if (rawDocument.cookie !== lastCookieString) {\n lastCookieString = rawDocument.cookie;\n cookieArray = lastCookieString.split(\"; \");\n lastCookies = {};\n\n for (i = 0; i < cookieArray.length; i++) {\n cookie = cookieArray[i];\n index = cookie.indexOf('=');\n if (index > 0) { //ignore nameless cookies\n name = safeDecodeURIComponent(cookie.substring(0, index));\n // the first value that is seen for a cookie is the most\n // specific one. values for the same cookie name that\n // follow are for less specific paths.\n if (lastCookies[name] === undefined) {\n lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));\n }\n }\n }\n }\n return lastCookies;\n }\n };\n\n\n /**\n * @name $browser#defer\n * @param {function()} fn A function, who's execution should be deferred.\n * @param {number=} [delay=0] of milliseconds to defer the function execution.\n * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n *\n * @description\n * Executes a fn asynchronously via `setTimeout(fn, delay)`.\n *\n * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n * via `$browser.defer.flush()`.\n *\n */\n self.defer = function(fn, delay) {\n var timeoutId;\n outstandingRequestCount++;\n timeoutId = setTimeout(function() {\n delete pendingDeferIds[timeoutId];\n completeOutstandingRequest(fn);\n }, delay || 0);\n pendingDeferIds[timeoutId] = true;\n return timeoutId;\n };\n\n\n /**\n * @name $browser#defer.cancel\n *\n * @description\n * Cancels a deferred task identified with `deferId`.\n *\n * @param {*} deferId Token returned by the `$browser.defer` function.\n * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n * canceled.\n */\n self.defer.cancel = function(deferId) {\n if (pendingDeferIds[deferId]) {\n delete pendingDeferIds[deferId];\n clearTimeout(deferId);\n completeOutstandingRequest(noop);\n return true;\n }\n return false;\n };\n\n}\n\nfunction $BrowserProvider() {\n this.$get = ['$window', '$log', '$sniffer', '$document',\n function($window, $log, $sniffer, $document) {\n return new Browser($window, $document, $log, $sniffer);\n }];\n}\n\n/**\n * @ngdoc service\n * @name $cacheFactory\n *\n * @description\n * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to\n * them.\n *\n * ```js\n *\n * var cache = $cacheFactory('cacheId');\n * expect($cacheFactory.get('cacheId')).toBe(cache);\n * expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();\n *\n * cache.put(\"key\", \"value\");\n * cache.put(\"another key\", \"another value\");\n *\n * // We've specified no options on creation\n * expect(cache.info()).toEqual({id: 'cacheId', size: 2});\n *\n * ```\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n * - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns\n * it.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n * @example\n \n \n
\n \n \n \n\n

Cached Values

\n
\n \n : \n \n
\n\n

Cache Info

\n
\n \n : \n \n
\n
\n
\n \n angular.module('cacheExampleApp', []).\n controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {\n $scope.keys = [];\n $scope.cache = $cacheFactory('cacheId');\n $scope.put = function(key, value) {\n if ($scope.cache.get(key) === undefined) {\n $scope.keys.push(key);\n }\n $scope.cache.put(key, value === undefined ? null : value);\n };\n }]);\n \n \n p {\n margin: 10px 0 3px;\n }\n \n
\n */\nfunction $CacheFactoryProvider() {\n\n this.$get = function() {\n var caches = {};\n\n function cacheFactory(cacheId, options) {\n if (cacheId in caches) {\n throw minErr('$cacheFactory')('iid', \"CacheId '{0}' is already taken!\", cacheId);\n }\n\n var size = 0,\n stats = extend({}, options, {id: cacheId}),\n data = {},\n capacity = (options && options.capacity) || Number.MAX_VALUE,\n lruHash = {},\n freshEnd = null,\n staleEnd = null;\n\n /**\n * @ngdoc type\n * @name $cacheFactory.Cache\n *\n * @description\n * A cache object used to store and retrieve data, primarily used by\n * {@link $http $http} and the {@link ng.directive:script script} directive to cache\n * templates and other data.\n *\n * ```js\n * angular.module('superCache')\n * .factory('superCache', ['$cacheFactory', function($cacheFactory) {\n * return $cacheFactory('super-cache');\n * }]);\n * ```\n *\n * Example test:\n *\n * ```js\n * it('should behave like a cache', inject(function(superCache) {\n * superCache.put('key', 'value');\n * superCache.put('another key', 'another value');\n *\n * expect(superCache.info()).toEqual({\n * id: 'super-cache',\n * size: 2\n * });\n *\n * superCache.remove('another key');\n * expect(superCache.get('another key')).toBeUndefined();\n *\n * superCache.removeAll();\n * expect(superCache.info()).toEqual({\n * id: 'super-cache',\n * size: 0\n * });\n * }));\n * ```\n */\n return caches[cacheId] = {\n\n /**\n * @ngdoc method\n * @name $cacheFactory.Cache#put\n * @kind function\n *\n * @description\n * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be\n * retrieved later, and incrementing the size of the cache if the key was not already\n * present in the cache. If behaving like an LRU cache, it will also remove stale\n * entries from the set.\n *\n * It will not insert undefined values into the cache.\n *\n * @param {string} key the key under which the cached data is stored.\n * @param {*} value the value to store alongside the key. If it is undefined, the key\n * will not be stored.\n * @returns {*} the value stored.\n */\n put: function(key, value) {\n if (capacity < Number.MAX_VALUE) {\n var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n refresh(lruEntry);\n }\n\n if (isUndefined(value)) return;\n if (!(key in data)) size++;\n data[key] = value;\n\n if (size > capacity) {\n this.remove(staleEnd.key);\n }\n\n return value;\n },\n\n /**\n * @ngdoc method\n * @name $cacheFactory.Cache#get\n * @kind function\n *\n * @description\n * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.\n *\n * @param {string} key the key of the data to be retrieved\n * @returns {*} the value stored.\n */\n get: function(key) {\n if (capacity < Number.MAX_VALUE) {\n var lruEntry = lruHash[key];\n\n if (!lruEntry) return;\n\n refresh(lruEntry);\n }\n\n return data[key];\n },\n\n\n /**\n * @ngdoc method\n * @name $cacheFactory.Cache#remove\n * @kind function\n *\n * @description\n * Removes an entry from the {@link $cacheFactory.Cache Cache} object.\n *\n * @param {string} key the key of the entry to be removed\n */\n remove: function(key) {\n if (capacity < Number.MAX_VALUE) {\n var lruEntry = lruHash[key];\n\n if (!lruEntry) return;\n\n if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n link(lruEntry.n,lruEntry.p);\n\n delete lruHash[key];\n }\n\n delete data[key];\n size--;\n },\n\n\n /**\n * @ngdoc method\n * @name $cacheFactory.Cache#removeAll\n * @kind function\n *\n * @description\n * Clears the cache object of any entries.\n */\n removeAll: function() {\n data = {};\n size = 0;\n lruHash = {};\n freshEnd = staleEnd = null;\n },\n\n\n /**\n * @ngdoc method\n * @name $cacheFactory.Cache#destroy\n * @kind function\n *\n * @description\n * Destroys the {@link $cacheFactory.Cache Cache} object entirely,\n * removing it from the {@link $cacheFactory $cacheFactory} set.\n */\n destroy: function() {\n data = null;\n stats = null;\n lruHash = null;\n delete caches[cacheId];\n },\n\n\n /**\n * @ngdoc method\n * @name $cacheFactory.Cache#info\n * @kind function\n *\n * @description\n * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.\n *\n * @returns {object} an object with the following properties:\n *
    \n *
  • **id**: the id of the cache instance
  • \n *
  • **size**: the number of entries kept in the cache instance
  • \n *
  • **...**: any additional properties from the options object when creating the\n * cache.
  • \n *
\n */\n info: function() {\n return extend({}, stats, {size: size});\n }\n };\n\n\n /**\n * makes the `entry` the freshEnd of the LRU linked list\n */\n function refresh(entry) {\n if (entry != freshEnd) {\n if (!staleEnd) {\n staleEnd = entry;\n } else if (staleEnd == entry) {\n staleEnd = entry.n;\n }\n\n link(entry.n, entry.p);\n link(entry, freshEnd);\n freshEnd = entry;\n freshEnd.n = null;\n }\n }\n\n\n /**\n * bidirectionally links two entries of the LRU linked list\n */\n function link(nextEntry, prevEntry) {\n if (nextEntry != prevEntry) {\n if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n }\n }\n }\n\n\n /**\n * @ngdoc method\n * @name $cacheFactory#info\n *\n * @description\n * Get information about all the caches that have been created\n *\n * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`\n */\n cacheFactory.info = function() {\n var info = {};\n forEach(caches, function(cache, cacheId) {\n info[cacheId] = cache.info();\n });\n return info;\n };\n\n\n /**\n * @ngdoc method\n * @name $cacheFactory#get\n *\n * @description\n * Get access to a cache object by the `cacheId` used when it was created.\n *\n * @param {string} cacheId Name or id of a cache to access.\n * @returns {object} Cache object identified by the cacheId or undefined if no such cache.\n */\n cacheFactory.get = function(cacheId) {\n return caches[cacheId];\n };\n\n\n return cacheFactory;\n };\n}\n\n/**\n * @ngdoc service\n * @name $templateCache\n *\n * @description\n * The first time a template is used, it is loaded in the template cache for quick retrieval. You\n * can load templates directly into the cache in a `script` tag, or by consuming the\n * `$templateCache` service directly.\n *\n * Adding via the `script` tag:\n *\n * ```html\n * \n * ```\n *\n * **Note:** the `script` tag containing the template does not need to be included in the `head` of\n * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,\n * element with ng-app attribute), otherwise the template will be ignored.\n *\n * Adding via the $templateCache service:\n *\n * ```js\n * var myApp = angular.module('myApp', []);\n * myApp.run(function($templateCache) {\n * $templateCache.put('templateId.html', 'This is the content of the template');\n * });\n * ```\n *\n * To retrieve the template later, simply use it in your HTML:\n * ```html\n *
\n * ```\n *\n * or get it via Javascript:\n * ```js\n * $templateCache.get('templateId.html')\n * ```\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n this.$get = ['$cacheFactory', function($cacheFactory) {\n return $cacheFactory('templates');\n }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" - function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\n/**\n * @ngdoc service\n * @name $compile\n * @kind function\n *\n * @description\n * Compiles an HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.\n *\n * The compilation is a process of walking the DOM tree and matching DOM elements to\n * {@link ng.$compileProvider#directive directives}.\n *\n *
\n * **Note:** This document is an in-depth reference of all directive options.\n * For a gentle introduction to directives with examples of common use cases,\n * see the {@link guide/directive directive guide}.\n *
\n *\n * ## Comprehensive Directive API\n *\n * There are many different options for a directive.\n *\n * The difference resides in the return value of the factory function.\n * You can either return a \"Directive Definition Object\" (see below) that defines the directive properties,\n * or just the `postLink` function (all other properties will have the default values).\n *\n *
\n * **Best Practice:** It's recommended to use the \"directive definition object\" form.\n *
\n *\n * Here's an example directive declared with a Directive Definition Object:\n *\n * ```js\n * var myModule = angular.module(...);\n *\n * myModule.directive('directiveName', function factory(injectables) {\n * var directiveDefinitionObject = {\n * priority: 0,\n * template: '
', // or // function(tElement, tAttrs) { ... },\n * // or\n * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },\n * transclude: false,\n * restrict: 'A',\n * templateNamespace: 'html',\n * scope: false,\n * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },\n * controllerAs: 'stringAlias',\n * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],\n * compile: function compile(tElement, tAttrs, transclude) {\n * return {\n * pre: function preLink(scope, iElement, iAttrs, controller) { ... },\n * post: function postLink(scope, iElement, iAttrs, controller) { ... }\n * }\n * // or\n * // return function postLink( ... ) { ... }\n * },\n * // or\n * // link: {\n * // pre: function preLink(scope, iElement, iAttrs, controller) { ... },\n * // post: function postLink(scope, iElement, iAttrs, controller) { ... }\n * // }\n * // or\n * // link: function postLink( ... ) { ... }\n * };\n * return directiveDefinitionObject;\n * });\n * ```\n *\n *
\n * **Note:** Any unspecified options will use the default value. You can see the default values below.\n *
\n *\n * Therefore the above can be simplified as:\n *\n * ```js\n * var myModule = angular.module(...);\n *\n * myModule.directive('directiveName', function factory(injectables) {\n * var directiveDefinitionObject = {\n * link: function postLink(scope, iElement, iAttrs) { ... }\n * };\n * return directiveDefinitionObject;\n * // or\n * // return function postLink(scope, iElement, iAttrs) { ... }\n * });\n * ```\n *\n *\n *\n * ### Directive Definition Object\n *\n * The directive definition object provides instructions to the {@link ng.$compile\n * compiler}. The attributes are:\n *\n * #### `multiElement`\n * When this property is set to true, the HTML compiler will collect DOM nodes between\n * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them\n * together as the directive elements. It is recommended that this feature be used on directives\n * which are not strictly behavioural (such as {@link ngClick}), and which\n * do not manipulate or replace child nodes (such as {@link ngInclude}).\n *\n * #### `priority`\n * When there are multiple directives defined on a single DOM element, sometimes it\n * is necessary to specify the order in which the directives are applied. The `priority` is used\n * to sort the directives before their `compile` functions get called. Priority is defined as a\n * number. Directives with greater numerical `priority` are compiled first. Pre-link functions\n * are also run in priority order, but post-link functions are run in reverse order. The order\n * of directives with the same priority is undefined. The default priority is `0`.\n *\n * #### `terminal`\n * If set to true then the current `priority` will be the last set of directives\n * which will execute (any directives at the current priority will still execute\n * as the order of execution on same `priority` is undefined). Note that expressions\n * and other directives used in the directive's template will also be excluded from execution.\n *\n * #### `scope`\n * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the\n * same element request a new scope, only one new scope is created. The new scope rule does not\n * apply for the root of the template since the root of the template always gets a new scope.\n *\n * **If set to `{}` (object hash),** then a new \"isolate\" scope is created. The 'isolate' scope differs from\n * normal scope in that it does not prototypically inherit from the parent scope. This is useful\n * when creating reusable components, which should not accidentally read or modify data in the\n * parent scope.\n *\n * The 'isolate' scope takes an object hash which defines a set of local scope properties\n * derived from the parent scope. These local properties are useful for aliasing values for\n * templates. Locals definition is a hash of local scope property to its source:\n *\n * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is\n * always a string since DOM attributes are strings. If no `attr` name is specified then the\n * attribute name is assumed to be the same as the local name.\n * Given `` and widget definition\n * of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect\n * the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the\n * `localName` property on the widget scope. The `name` is read from the parent scope (not\n * component scope).\n *\n * * `=` or `=attr` - set up bi-directional binding between a local scope property and the\n * parent scope property of name defined via the value of the `attr` attribute. If no `attr`\n * name is specified then the attribute name is assumed to be the same as the local name.\n * Given `` and widget definition of\n * `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the\n * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected\n * in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent\n * scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You\n * can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If\n * you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use\n * `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).\n *\n * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.\n * If no `attr` name is specified then the attribute name is assumed to be the same as the\n * local name. Given `` and widget definition of\n * `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to\n * a function wrapper for the `count = count + value` expression. Often it's desirable to\n * pass data from the isolated scope via an expression to the parent scope, this can be\n * done by passing a map of local variable names and values into the expression wrapper fn.\n * For example, if the expression is `increment(amount)` then we can specify the amount value\n * by calling the `localFn` as `localFn({amount: 22})`.\n *\n *\n * #### `bindToController`\n * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will\n * allow a component to have its properties bound to the controller, rather than to scope. When the controller\n * is instantiated, the initial values of the isolate scope bindings are already available.\n *\n * #### `controller`\n * Controller constructor function. The controller is instantiated before the\n * pre-linking phase and it is shared with other directives (see\n * `require` attribute). This allows the directives to communicate with each other and augment\n * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:\n *\n * * `$scope` - Current scope associated with the element\n * * `$element` - Current element\n * * `$attrs` - Current attributes object for the element\n * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:\n * `function([scope], cloneLinkingFn, futureParentElement)`.\n * * `scope`: optional argument to override the scope.\n * * `cloneLinkingFn`: optional argument to create clones of the original transcluded content.\n * * `futureParentElement`:\n * * defines the parent to which the `cloneLinkingFn` will add the cloned elements.\n * * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`.\n * * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements)\n * and when the `cloneLinkinFn` is passed,\n * as those elements need to created and cloned in a special way when they are defined outside their\n * usual containers (e.g. like ``).\n * * See also the `directive.templateNamespace` property.\n *\n *\n * #### `require`\n * Require another directive and inject its controller as the fourth argument to the linking function. The\n * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the\n * injected argument will be an array in corresponding order. If no such directive can be\n * found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with:\n *\n * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.\n * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.\n * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.\n * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found.\n * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass\n * `null` to the `link` fn if not found.\n * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass\n * `null` to the `link` fn if not found.\n *\n *\n * #### `controllerAs`\n * Controller alias at the directive scope. An alias for the controller so it\n * can be referenced at the directive template. The directive needs to define a scope for this\n * configuration to be used. Useful in the case when directive is used as component.\n *\n *\n * #### `restrict`\n * String of subset of `EACM` which restricts the directive to a specific directive\n * declaration style. If omitted, the defaults (elements and attributes) are used.\n *\n * * `E` - Element name (default): ``\n * * `A` - Attribute (default): `
`\n * * `C` - Class: `
`\n * * `M` - Comment: ``\n *\n *\n * #### `templateNamespace`\n * String representing the document type used by the markup in the template.\n * AngularJS needs this information as those elements need to be created and cloned\n * in a special way when they are defined outside their usual containers like `` and ``.\n *\n * * `html` - All root nodes in the template are HTML. Root nodes may also be\n * top-level elements such as `` or ``.\n * * `svg` - The root nodes in the template are SVG elements (excluding ``).\n * * `math` - The root nodes in the template are MathML elements (excluding ``).\n *\n * If no `templateNamespace` is specified, then the namespace is considered to be `html`.\n *\n * #### `template`\n * HTML markup that may:\n * * Replace the contents of the directive's element (default).\n * * Replace the directive's element itself (if `replace` is true - DEPRECATED).\n * * Wrap the contents of the directive's element (if `transclude` is true).\n *\n * Value may be:\n *\n * * A string. For example `
{{delete_str}}
`.\n * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`\n * function api below) and returns a string value.\n *\n *\n * #### `templateUrl`\n * This is similar to `template` but the template is loaded from the specified URL, asynchronously.\n *\n * Because template loading is asynchronous the compiler will suspend compilation of directives on that element\n * for later when the template has been resolved. In the meantime it will continue to compile and link\n * sibling and parent elements as though this element had not contained any directives.\n *\n * The compiler does not suspend the entire compilation to wait for templates to be loaded because this\n * would result in the whole app \"stalling\" until all templates are loaded asynchronously - even in the\n * case when only one deeply nested directive has `templateUrl`.\n *\n * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache}\n *\n * You can specify `templateUrl` as a string representing the URL or as a function which takes two\n * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns\n * a string value representing the url. In either case, the template URL is passed through {@link\n * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.\n *\n *\n * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0)\n * specify what the template should replace. Defaults to `false`.\n *\n * * `true` - the template will replace the directive's element.\n * * `false` - the template will replace the contents of the directive's element.\n *\n * The replacement process migrates all of the attributes / classes from the old element to the new\n * one. See the {@link guide/directive#template-expanding-directive\n * Directives Guide} for an example.\n *\n * There are very few scenarios where element replacement is required for the application function,\n * the main one being reusable custom components that are used within SVG contexts\n * (because SVG doesn't work with custom elements in the DOM tree).\n *\n * #### `transclude`\n * Extract the contents of the element where the directive appears and make it available to the directive.\n * The contents are compiled and provided to the directive as a **transclusion function**. See the\n * {@link $compile#transclusion Transclusion} section below.\n *\n * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the\n * directive's element or the entire element:\n *\n * * `true` - transclude the content (i.e. the child nodes) of the directive's element.\n * * `'element'` - transclude the whole of the directive's element including any directives on this\n * element that defined at a lower priority than this directive. When used, the `template`\n * property is ignored.\n *\n *\n * #### `compile`\n *\n * ```js\n * function compile(tElement, tAttrs, transclude) { ... }\n * ```\n *\n * The compile function deals with transforming the template DOM. Since most directives do not do\n * template transformation, it is not used often. The compile function takes the following arguments:\n *\n * * `tElement` - template element - The element where the directive has been declared. It is\n * safe to do template transformation on the element and child elements only.\n *\n * * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared\n * between all directive compile functions.\n *\n * * `transclude` - [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`\n *\n *
\n * **Note:** The template instance and the link instance may be different objects if the template has\n * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that\n * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration\n * should be done in a linking function rather than in a compile function.\n *
\n\n *
\n * **Note:** The compile function cannot handle directives that recursively use themselves in their\n * own templates or compile functions. Compiling these directives results in an infinite loop and a\n * stack overflow errors.\n *\n * This can be avoided by manually using $compile in the postLink function to imperatively compile\n * a directive's template instead of relying on automatic template compilation via `template` or\n * `templateUrl` declaration or manual compilation inside the compile function.\n *
\n *\n *
\n * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it\n * e.g. does not know about the right outer scope. Please use the transclude function that is passed\n * to the link function instead.\n *
\n\n * A compile function can have a return value which can be either a function or an object.\n *\n * * returning a (post-link) function - is equivalent to registering the linking function via the\n * `link` property of the config object when the compile function is empty.\n *\n * * returning an object with function(s) registered via `pre` and `post` properties - allows you to\n * control when a linking function should be called during the linking phase. See info about\n * pre-linking and post-linking functions below.\n *\n *\n * #### `link`\n * This property is used only if the `compile` property is not defined.\n *\n * ```js\n * function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }\n * ```\n *\n * The link function is responsible for registering DOM listeners as well as updating the DOM. It is\n * executed after the template has been cloned. This is where most of the directive logic will be\n * put.\n *\n * * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the\n * directive for registering {@link ng.$rootScope.Scope#$watch watches}.\n *\n * * `iElement` - instance element - The element where the directive is to be used. It is safe to\n * manipulate the children of the element only in `postLink` function since the children have\n * already been linked.\n *\n * * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared\n * between all directive linking functions.\n *\n * * `controller` - a controller instance - A controller instance if at least one directive on the\n * element defines a controller. The controller is shared among all the directives, which allows\n * the directives to use the controllers as a communication channel.\n *\n * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.\n * This is the same as the `$transclude`\n * parameter of directive controllers, see there for details.\n * `function([scope], cloneLinkingFn, futureParentElement)`.\n *\n * #### Pre-linking function\n *\n * Executed before the child elements are linked. Not safe to do DOM transformation since the\n * compiler linking function will fail to locate the correct elements for linking.\n *\n * #### Post-linking function\n *\n * Executed after the child elements are linked.\n *\n * Note that child elements that contain `templateUrl` directives will not have been compiled\n * and linked since they are waiting for their template to load asynchronously and their own\n * compilation and linking has been suspended until that occurs.\n *\n * It is safe to do DOM transformation in the post-linking function on elements that are not waiting\n * for their async templates to be resolved.\n *\n *\n * ### Transclusion\n *\n * Transclusion is the process of extracting a collection of DOM element from one part of the DOM and\n * copying them to another part of the DOM, while maintaining their connection to the original AngularJS\n * scope from where they were taken.\n *\n * Transclusion is used (often with {@link ngTransclude}) to insert the\n * original contents of a directive's element into a specified place in the template of the directive.\n * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded\n * content has access to the properties on the scope from which it was taken, even if the directive\n * has isolated scope.\n * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}.\n *\n * This makes it possible for the widget to have private state for its template, while the transcluded\n * content has access to its originating scope.\n *\n *
\n * **Note:** When testing an element transclude directive you must not place the directive at the root of the\n * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives\n * Testing Transclusion Directives}.\n *
\n *\n * #### Transclusion Functions\n *\n * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion\n * function** to the directive's `link` function and `controller`. This transclusion function is a special\n * **linking function** that will return the compiled contents linked to a new transclusion scope.\n *\n *
\n * If you are just using {@link ngTransclude} then you don't need to worry about this function, since\n * ngTransclude will deal with it for us.\n *
\n *\n * If you want to manually control the insertion and removal of the transcluded content in your directive\n * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery\n * object that contains the compiled DOM, which is linked to the correct transclusion scope.\n *\n * When you call a transclusion function you can pass in a **clone attach function**. This function accepts\n * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded\n * content and the `scope` is the newly created transclusion scope, to which the clone is bound.\n *\n *
\n * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function\n * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope.\n *
\n *\n * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone\n * attach function**:\n *\n * ```js\n * var transcludedContent, transclusionScope;\n *\n * $transclude(function(clone, scope) {\n * element.append(clone);\n * transcludedContent = clone;\n * transclusionScope = scope;\n * });\n * ```\n *\n * Later, if you want to remove the transcluded content from your DOM then you should also destroy the\n * associated transclusion scope:\n *\n * ```js\n * transcludedContent.remove();\n * transclusionScope.$destroy();\n * ```\n *\n *
\n * **Best Practice**: if you intend to add and remove transcluded content manually in your directive\n * (by calling the transclude function to get the DOM and and calling `element.remove()` to remove it),\n * then you are also responsible for calling `$destroy` on the transclusion scope.\n *
\n *\n * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat}\n * automatically destroy their transluded clones as necessary so you do not need to worry about this if\n * you are simply using {@link ngTransclude} to inject the transclusion into your directive.\n *\n *\n * #### Transclusion Scopes\n *\n * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion\n * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed\n * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it\n * was taken.\n *\n * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look\n * like this:\n *\n * ```html\n *
\n *
\n *
\n *
\n *
\n *
\n * ```\n *\n * The `$parent` scope hierarchy will look like this:\n *\n * ```\n * - $rootScope\n * - isolate\n * - transclusion\n * ```\n *\n * but the scopes will inherit prototypically from different scopes to their `$parent`.\n *\n * ```\n * - $rootScope\n * - transclusion\n * - isolate\n * ```\n *\n *\n * ### Attributes\n *\n * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the\n * `link()` or `compile()` functions. It has a variety of uses.\n *\n * accessing *Normalized attribute names:*\n * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'.\n * the attributes object allows for normalized access to\n * the attributes.\n *\n * * *Directive inter-communication:* All directives share the same instance of the attributes\n * object which allows the directives to use the attributes object as inter directive\n * communication.\n *\n * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object\n * allowing other directives to read the interpolated value.\n *\n * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes\n * that contain interpolation (e.g. `src=\"{{bar}}\"`). Not only is this very efficient but it's also\n * the only way to easily get the actual value because during the linking phase the interpolation\n * hasn't been evaluated yet and so the value is at this time set to `undefined`.\n *\n * ```js\n * function linkingFn(scope, elm, attrs, ctrl) {\n * // get the attribute value\n * console.log(attrs.ngModel);\n *\n * // change the attribute\n * attrs.$set('ngModel', 'new value');\n *\n * // observe changes to interpolated attribute\n * attrs.$observe('ngModel', function(value) {\n * console.log('ngModel has changed value to ' + value);\n * });\n * }\n * ```\n *\n * ## Example\n *\n *
\n * **Note**: Typically directives are registered with `module.directive`. The example below is\n * to illustrate how `$compile` works.\n *
\n *\n \n \n \n
\n
\n
\n
\n
\n
\n \n it('should auto compile', function() {\n var textarea = $('textarea');\n var output = $('div[compile]');\n // The initial state reads 'Hello Angular'.\n expect(output.getText()).toBe('Hello Angular');\n textarea.clear();\n textarea.sendKeys('{{name}}!');\n expect(output.getText()).toBe('Angular!');\n });\n \n
\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED.\n *\n *
\n * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it\n * e.g. will not use the right outer scope. Please pass the transclude function as a\n * `parentBoundTranscludeFn` to the link function instead.\n *
\n *\n * @param {number} maxPriority only apply directives lower than given priority (Only effects the\n * root element(s), not their children)\n * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n * `template` and call the `cloneAttachFn` function allowing the caller to attach the\n * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n * called as:
`cloneAttachFn(clonedElement, scope)` where:\n *\n * * `clonedElement` - is a clone of the original `element` passed into the compiler.\n * * `scope` - is the current scope with which the linking function is working with.\n *\n * * `options` - An optional object hash with linking options. If `options` is provided, then the following\n * keys may be used to control linking behavior:\n *\n * * `parentBoundTranscludeFn` - the transclude function made available to\n * directives; if given, it will be passed through to the link functions of\n * directives found in `element` during compilation.\n * * `transcludeControllers` - an object hash with keys that map controller names\n * to controller instances; if given, it will make the controllers\n * available to directives.\n * * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add\n * the cloned elements; only needed for transcludes that are allowed to contain non html\n * elements (e.g. SVG elements). See also the directive.controller property.\n *\n * Calling the linking function returns the element of the template. It is either the original\n * element passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n * before you send them to the compiler and keep this reference around.\n * ```js\n * var element = $compile('

{{total}}

')(scope);\n * ```\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n * example would not point to the clone, but rather to the original template that was cloned. In\n * this case, you can access the clone via the cloneAttachFn:\n * ```js\n * var templateElement = angular.element('

{{total}}

'),\n * scope = ....;\n *\n * var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {\n * //attach the clone to DOM document at the right place\n * });\n *\n * //now we have reference to the cloned DOM via `clonedElement`\n * ```\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\nvar $compileMinErr = minErr('$compile');\n\n/**\n * @ngdoc provider\n * @name $compileProvider\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];\nfunction $CompileProvider($provide, $$sanitizeUriProvider) {\n var hasDirectives = {},\n Suffix = 'Directive',\n COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\w\\-]+)\\s+(.*)$/,\n CLASS_DIRECTIVE_REGEXP = /(([\\w\\-]+)(?:\\:([^;]+))?;?)/,\n ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),\n REQUIRE_PREFIX_REGEXP = /^(?:(\\^\\^?)?(\\?)?(\\^\\^?)?)?/;\n\n // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes\n // The assumption is that future DOM event attribute names will begin with\n // 'on' and be composed of only English letters.\n var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;\n\n function parseIsolateBindings(scope, directiveName) {\n var LOCAL_REGEXP = /^\\s*([@&]|=(\\*?))(\\??)\\s*(\\w*)\\s*$/;\n\n var bindings = {};\n\n forEach(scope, function(definition, scopeName) {\n var match = definition.match(LOCAL_REGEXP);\n\n if (!match) {\n throw $compileMinErr('iscp',\n \"Invalid isolate scope definition for directive '{0}'.\" +\n \" Definition: {... {1}: '{2}' ...}\",\n directiveName, scopeName, definition);\n }\n\n bindings[scopeName] = {\n mode: match[1][0],\n collection: match[2] === '*',\n optional: match[3] === '?',\n attrName: match[4] || scopeName\n };\n });\n\n return bindings;\n }\n\n /**\n * @ngdoc method\n * @name $compileProvider#directive\n * @kind function\n *\n * @description\n * Register a new directive with the compiler.\n *\n * @param {string|Object} name Name of the directive in camel-case (i.e. ngBind which\n * will match as ng-bind), or an object map of directives where the keys are the\n * names and the values are the factories.\n * @param {Function|Array} directiveFactory An injectable directive factory function. See\n * {@link guide/directive} for more info.\n * @returns {ng.$compileProvider} Self for chaining.\n */\n this.directive = function registerDirective(name, directiveFactory) {\n assertNotHasOwnProperty(name, 'directive');\n if (isString(name)) {\n assertArg(directiveFactory, 'directiveFactory');\n if (!hasDirectives.hasOwnProperty(name)) {\n hasDirectives[name] = [];\n $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n function($injector, $exceptionHandler) {\n var directives = [];\n forEach(hasDirectives[name], function(directiveFactory, index) {\n try {\n var directive = $injector.invoke(directiveFactory);\n if (isFunction(directive)) {\n directive = { compile: valueFn(directive) };\n } else if (!directive.compile && directive.link) {\n directive.compile = valueFn(directive.link);\n }\n directive.priority = directive.priority || 0;\n directive.index = index;\n directive.name = directive.name || name;\n directive.require = directive.require || (directive.controller && directive.name);\n directive.restrict = directive.restrict || 'EA';\n if (isObject(directive.scope)) {\n directive.$$isolateBindings = parseIsolateBindings(directive.scope, directive.name);\n }\n directives.push(directive);\n } catch (e) {\n $exceptionHandler(e);\n }\n });\n return directives;\n }]);\n }\n hasDirectives[name].push(directiveFactory);\n } else {\n forEach(name, reverseParams(registerDirective));\n }\n return this;\n };\n\n\n /**\n * @ngdoc method\n * @name $compileProvider#aHrefSanitizationWhitelist\n * @kind function\n *\n * @description\n * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n * urls during a[href] sanitization.\n *\n * The sanitization is a security measure aimed at preventing XSS attacks via html links.\n *\n * Any url about to be assigned to a[href] via data-binding is first normalized and turned into\n * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`\n * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n *\n * @param {RegExp=} regexp New regexp to whitelist urls with.\n * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n * chaining otherwise.\n */\n this.aHrefSanitizationWhitelist = function(regexp) {\n if (isDefined(regexp)) {\n $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);\n return this;\n } else {\n return $$sanitizeUriProvider.aHrefSanitizationWhitelist();\n }\n };\n\n\n /**\n * @ngdoc method\n * @name $compileProvider#imgSrcSanitizationWhitelist\n * @kind function\n *\n * @description\n * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n * urls during img[src] sanitization.\n *\n * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n *\n * Any url about to be assigned to img[src] via data-binding is first normalized and turned into\n * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`\n * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n *\n * @param {RegExp=} regexp New regexp to whitelist urls with.\n * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n * chaining otherwise.\n */\n this.imgSrcSanitizationWhitelist = function(regexp) {\n if (isDefined(regexp)) {\n $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);\n return this;\n } else {\n return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();\n }\n };\n\n /**\n * @ngdoc method\n * @name $compileProvider#debugInfoEnabled\n *\n * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the\n * current debugInfoEnabled state\n * @returns {*} current value if used as getter or itself (chaining) if used as setter\n *\n * @kind function\n *\n * @description\n * Call this method to enable/disable various debug runtime information in the compiler such as adding\n * binding information and a reference to the current scope on to DOM elements.\n * If enabled, the compiler will add the following to DOM elements that have been bound to the scope\n * * `ng-binding` CSS class\n * * `$binding` data property containing an array of the binding expressions\n *\n * You may want to disable this in production for a significant performance boost. See\n * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.\n *\n * The default value is true.\n */\n var debugInfoEnabled = true;\n this.debugInfoEnabled = function(enabled) {\n if (isDefined(enabled)) {\n debugInfoEnabled = enabled;\n return this;\n }\n return debugInfoEnabled;\n };\n\n this.$get = [\n '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',\n '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',\n function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse,\n $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) {\n\n var Attributes = function(element, attributesToCopy) {\n if (attributesToCopy) {\n var keys = Object.keys(attributesToCopy);\n var i, l, key;\n\n for (i = 0, l = keys.length; i < l; i++) {\n key = keys[i];\n this[key] = attributesToCopy[key];\n }\n } else {\n this.$attr = {};\n }\n\n this.$$element = element;\n };\n\n Attributes.prototype = {\n /**\n * @ngdoc method\n * @name $compile.directive.Attributes#$normalize\n * @kind function\n *\n * @description\n * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or\n * `data-`) to its normalized, camelCase form.\n *\n * Also there is special case for Moz prefix starting with upper case letter.\n *\n * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}\n *\n * @param {string} name Name to normalize\n */\n $normalize: directiveNormalize,\n\n\n /**\n * @ngdoc method\n * @name $compile.directive.Attributes#$addClass\n * @kind function\n *\n * @description\n * Adds the CSS class value specified by the classVal parameter to the element. If animations\n * are enabled then an animation will be triggered for the class addition.\n *\n * @param {string} classVal The className value that will be added to the element\n */\n $addClass: function(classVal) {\n if (classVal && classVal.length > 0) {\n $animate.addClass(this.$$element, classVal);\n }\n },\n\n /**\n * @ngdoc method\n * @name $compile.directive.Attributes#$removeClass\n * @kind function\n *\n * @description\n * Removes the CSS class value specified by the classVal parameter from the element. If\n * animations are enabled then an animation will be triggered for the class removal.\n *\n * @param {string} classVal The className value that will be removed from the element\n */\n $removeClass: function(classVal) {\n if (classVal && classVal.length > 0) {\n $animate.removeClass(this.$$element, classVal);\n }\n },\n\n /**\n * @ngdoc method\n * @name $compile.directive.Attributes#$updateClass\n * @kind function\n *\n * @description\n * Adds and removes the appropriate CSS class values to the element based on the difference\n * between the new and old CSS class values (specified as newClasses and oldClasses).\n *\n * @param {string} newClasses The current CSS className value\n * @param {string} oldClasses The former CSS className value\n */\n $updateClass: function(newClasses, oldClasses) {\n var toAdd = tokenDifference(newClasses, oldClasses);\n if (toAdd && toAdd.length) {\n $animate.addClass(this.$$element, toAdd);\n }\n\n var toRemove = tokenDifference(oldClasses, newClasses);\n if (toRemove && toRemove.length) {\n $animate.removeClass(this.$$element, toRemove);\n }\n },\n\n /**\n * Set a normalized attribute on the element in a way such that all directives\n * can share the attribute. This function properly handles boolean attributes.\n * @param {string} key Normalized key. (ie ngAttribute)\n * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n * Defaults to true.\n * @param {string=} attrName Optional none normalized name. Defaults to key.\n */\n $set: function(key, value, writeAttr, attrName) {\n // TODO: decide whether or not to throw an error if \"class\"\n //is set through this function since it may cause $updateClass to\n //become unstable.\n\n var node = this.$$element[0],\n booleanKey = getBooleanAttrName(node, key),\n aliasedKey = getAliasedAttrName(node, key),\n observer = key,\n nodeName;\n\n if (booleanKey) {\n this.$$element.prop(key, value);\n attrName = booleanKey;\n } else if (aliasedKey) {\n this[aliasedKey] = value;\n observer = aliasedKey;\n }\n\n this[key] = value;\n\n // translate normalized key to actual key\n if (attrName) {\n this.$attr[key] = attrName;\n } else {\n attrName = this.$attr[key];\n if (!attrName) {\n this.$attr[key] = attrName = snake_case(key, '-');\n }\n }\n\n nodeName = nodeName_(this.$$element);\n\n if ((nodeName === 'a' && key === 'href') ||\n (nodeName === 'img' && key === 'src')) {\n // sanitize a[href] and img[src] values\n this[key] = value = $$sanitizeUri(value, key === 'src');\n } else if (nodeName === 'img' && key === 'srcset') {\n // sanitize img[srcset] values\n var result = \"\";\n\n // first check if there are spaces because it's not the same pattern\n var trimmedSrcset = trim(value);\n // ( 999x ,| 999w ,| ,|, )\n var srcPattern = /(\\s+\\d+x\\s*,|\\s+\\d+w\\s*,|\\s+,|,\\s+)/;\n var pattern = /\\s/.test(trimmedSrcset) ? srcPattern : /(,)/;\n\n // split srcset into tuple of uri and descriptor except for the last item\n var rawUris = trimmedSrcset.split(pattern);\n\n // for each tuples\n var nbrUrisWith2parts = Math.floor(rawUris.length / 2);\n for (var i = 0; i < nbrUrisWith2parts; i++) {\n var innerIdx = i * 2;\n // sanitize the uri\n result += $$sanitizeUri(trim(rawUris[innerIdx]), true);\n // add the descriptor\n result += (\" \" + trim(rawUris[innerIdx + 1]));\n }\n\n // split the last item into uri and descriptor\n var lastTuple = trim(rawUris[i * 2]).split(/\\s/);\n\n // sanitize the last uri\n result += $$sanitizeUri(trim(lastTuple[0]), true);\n\n // and add the last descriptor if any\n if (lastTuple.length === 2) {\n result += (\" \" + trim(lastTuple[1]));\n }\n this[key] = value = result;\n }\n\n if (writeAttr !== false) {\n if (value === null || value === undefined) {\n this.$$element.removeAttr(attrName);\n } else {\n this.$$element.attr(attrName, value);\n }\n }\n\n // fire observers\n var $$observers = this.$$observers;\n $$observers && forEach($$observers[observer], function(fn) {\n try {\n fn(value);\n } catch (e) {\n $exceptionHandler(e);\n }\n });\n },\n\n\n /**\n * @ngdoc method\n * @name $compile.directive.Attributes#$observe\n * @kind function\n *\n * @description\n * Observes an interpolated attribute.\n *\n * The observer function will be invoked once during the next `$digest` following\n * compilation. The observer is then invoked whenever the interpolated value\n * changes.\n *\n * @param {string} key Normalized key. (ie ngAttribute) .\n * @param {function(interpolatedValue)} fn Function that will be called whenever\n the interpolated value of the attribute changes.\n * See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info.\n * @returns {function()} Returns a deregistration function for this observer.\n */\n $observe: function(key, fn) {\n var attrs = this,\n $$observers = (attrs.$$observers || (attrs.$$observers = createMap())),\n listeners = ($$observers[key] || ($$observers[key] = []));\n\n listeners.push(fn);\n $rootScope.$evalAsync(function() {\n if (!listeners.$$inter && attrs.hasOwnProperty(key)) {\n // no one registered attribute interpolation function, so lets call it manually\n fn(attrs[key]);\n }\n });\n\n return function() {\n arrayRemove(listeners, fn);\n };\n }\n };\n\n\n function safeAddClass($element, className) {\n try {\n $element.addClass(className);\n } catch (e) {\n // ignore, since it means that we are trying to set class on\n // SVG element, where class name is read-only.\n }\n }\n\n\n var startSymbol = $interpolate.startSymbol(),\n endSymbol = $interpolate.endSymbol(),\n denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}')\n ? identity\n : function denormalizeTemplate(template) {\n return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n },\n NG_ATTR_BINDING = /^ngAttr[A-Z]/;\n\n compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {\n var bindings = $element.data('$binding') || [];\n\n if (isArray(binding)) {\n bindings = bindings.concat(binding);\n } else {\n bindings.push(binding);\n }\n\n $element.data('$binding', bindings);\n } : noop;\n\n compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) {\n safeAddClass($element, 'ng-binding');\n } : noop;\n\n compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) {\n var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope';\n $element.data(dataName, scope);\n } : noop;\n\n compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) {\n safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope');\n } : noop;\n\n return compile;\n\n //================================\n\n function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,\n previousCompileContext) {\n if (!($compileNodes instanceof jqLite)) {\n // jquery always rewraps, whereas we need to preserve the original selector so that we can\n // modify it.\n $compileNodes = jqLite($compileNodes);\n }\n // We can not compile top level text elements since text nodes can be merged and we will\n // not be able to attach scope data to them, so we will wrap them in \n forEach($compileNodes, function(node, index) {\n if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n $compileNodes[index] = jqLite(node).wrap('').parent()[0];\n }\n });\n var compositeLinkFn =\n compileNodes($compileNodes, transcludeFn, $compileNodes,\n maxPriority, ignoreDirective, previousCompileContext);\n compile.$$addScopeClass($compileNodes);\n var namespace = null;\n return function publicLinkFn(scope, cloneConnectFn, options) {\n assertArg(scope, 'scope');\n\n options = options || {};\n var parentBoundTranscludeFn = options.parentBoundTranscludeFn,\n transcludeControllers = options.transcludeControllers,\n futureParentElement = options.futureParentElement;\n\n // When `parentBoundTranscludeFn` is passed, it is a\n // `controllersBoundTransclude` function (it was previously passed\n // as `transclude` to directive.link) so we must unwrap it to get\n // its `boundTranscludeFn`\n if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) {\n parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude;\n }\n\n if (!namespace) {\n namespace = detectNamespaceForChildElements(futureParentElement);\n }\n var $linkNode;\n if (namespace !== 'html') {\n // When using a directive with replace:true and templateUrl the $compileNodes\n // (or a child element inside of them)\n // might change, so we need to recreate the namespace adapted compileNodes\n // for call to the link function.\n // Note: This will already clone the nodes...\n $linkNode = jqLite(\n wrapTemplate(namespace, jqLite('
').append($compileNodes).html())\n );\n } else if (cloneConnectFn) {\n // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n // and sometimes changes the structure of the DOM.\n $linkNode = JQLitePrototype.clone.call($compileNodes);\n } else {\n $linkNode = $compileNodes;\n }\n\n if (transcludeControllers) {\n for (var controllerName in transcludeControllers) {\n $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance);\n }\n }\n\n compile.$$addScopeInfo($linkNode, scope);\n\n if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);\n return $linkNode;\n };\n }\n\n function detectNamespaceForChildElements(parentElement) {\n // TODO: Make this detect MathML as well...\n var node = parentElement && parentElement[0];\n if (!node) {\n return 'html';\n } else {\n return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html';\n }\n }\n\n /**\n * Compile function matches each node in nodeList against the directives. Once all directives\n * for a particular node are collected their compile functions are executed. The compile\n * functions return values - the linking functions - are combined into a composite linking\n * function, which is the a linking function for the node.\n *\n * @param {NodeList} nodeList an array of nodes or NodeList to compile\n * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n * scope argument is auto-generated to the new child of the transcluded parent scope.\n * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then\n * the rootElement must be set the jqLite collection of the compile root. This is\n * needed so that the jqLite collection items can be replaced with widgets.\n * @param {number=} maxPriority Max directive priority.\n * @returns {Function} A composite linking function of all of the matched directives or null.\n */\n function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,\n previousCompileContext) {\n var linkFns = [],\n attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound;\n\n for (var i = 0; i < nodeList.length; i++) {\n attrs = new Attributes();\n\n // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,\n ignoreDirective);\n\n nodeLinkFn = (directives.length)\n ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,\n null, [], [], previousCompileContext)\n : null;\n\n if (nodeLinkFn && nodeLinkFn.scope) {\n compile.$$addScopeClass(attrs.$$element);\n }\n\n childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||\n !(childNodes = nodeList[i].childNodes) ||\n !childNodes.length)\n ? null\n : compileNodes(childNodes,\n nodeLinkFn ? (\n (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)\n && nodeLinkFn.transclude) : transcludeFn);\n\n if (nodeLinkFn || childLinkFn) {\n linkFns.push(i, nodeLinkFn, childLinkFn);\n linkFnFound = true;\n nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;\n }\n\n //use the previous context only for the first element in the virtual group\n previousCompileContext = null;\n }\n\n // return a linking function if we have found anything, null otherwise\n return linkFnFound ? compositeLinkFn : null;\n\n function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {\n var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn;\n var stableNodeList;\n\n\n if (nodeLinkFnFound) {\n // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our\n // offsets don't get screwed up\n var nodeListLength = nodeList.length;\n stableNodeList = new Array(nodeListLength);\n\n // create a sparse array by only copying the elements which have a linkFn\n for (i = 0; i < linkFns.length; i+=3) {\n idx = linkFns[i];\n stableNodeList[idx] = nodeList[idx];\n }\n } else {\n stableNodeList = nodeList;\n }\n\n for (i = 0, ii = linkFns.length; i < ii;) {\n node = stableNodeList[linkFns[i++]];\n nodeLinkFn = linkFns[i++];\n childLinkFn = linkFns[i++];\n\n if (nodeLinkFn) {\n if (nodeLinkFn.scope) {\n childScope = scope.$new();\n compile.$$addScopeInfo(jqLite(node), childScope);\n } else {\n childScope = scope;\n }\n\n if (nodeLinkFn.transcludeOnThisElement) {\n childBoundTranscludeFn = createBoundTranscludeFn(\n scope, nodeLinkFn.transclude, parentBoundTranscludeFn,\n nodeLinkFn.elementTranscludeOnThisElement);\n\n } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {\n childBoundTranscludeFn = parentBoundTranscludeFn;\n\n } else if (!parentBoundTranscludeFn && transcludeFn) {\n childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);\n\n } else {\n childBoundTranscludeFn = null;\n }\n\n nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);\n\n } else if (childLinkFn) {\n childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);\n }\n }\n }\n }\n\n function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn, elementTransclusion) {\n\n var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {\n\n if (!transcludedScope) {\n transcludedScope = scope.$new(false, containingScope);\n transcludedScope.$$transcluded = true;\n }\n\n return transcludeFn(transcludedScope, cloneFn, {\n parentBoundTranscludeFn: previousBoundTranscludeFn,\n transcludeControllers: controllers,\n futureParentElement: futureParentElement\n });\n };\n\n return boundTranscludeFn;\n }\n\n /**\n * Looks for directives on the given node and adds them to the directive collection which is\n * sorted.\n *\n * @param node Node to search.\n * @param directives An array to which the directives are added to. This array is sorted before\n * the function returns.\n * @param attrs The shared attrs object which is used to populate the normalized attributes.\n * @param {number=} maxPriority Max directive priority.\n */\n function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {\n var nodeType = node.nodeType,\n attrsMap = attrs.$attr,\n match,\n className;\n\n switch (nodeType) {\n case NODE_TYPE_ELEMENT: /* Element */\n // use the node name: \n addDirective(directives,\n directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);\n\n // iterate over the attributes\n for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,\n j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n var attrStartName = false;\n var attrEndName = false;\n\n attr = nAttrs[j];\n name = attr.name;\n value = trim(attr.value);\n\n // support ngAttr attribute binding\n ngAttrName = directiveNormalize(name);\n if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {\n name = name.replace(PREFIX_REGEXP, '')\n .substr(8).replace(/_(.)/g, function(match, letter) {\n return letter.toUpperCase();\n });\n }\n\n var directiveNName = ngAttrName.replace(/(Start|End)$/, '');\n if (directiveIsMultiElement(directiveNName)) {\n if (ngAttrName === directiveNName + 'Start') {\n attrStartName = name;\n attrEndName = name.substr(0, name.length - 5) + 'end';\n name = name.substr(0, name.length - 6);\n }\n }\n\n nName = directiveNormalize(name.toLowerCase());\n attrsMap[nName] = name;\n if (isNgAttr || !attrs.hasOwnProperty(nName)) {\n attrs[nName] = value;\n if (getBooleanAttrName(node, nName)) {\n attrs[nName] = true; // presence means true\n }\n }\n addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);\n addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,\n attrEndName);\n }\n\n // use class as directive\n className = node.className;\n if (isObject(className)) {\n // Maybe SVGAnimatedString\n className = className.animVal;\n }\n if (isString(className) && className !== '') {\n while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n nName = directiveNormalize(match[2]);\n if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {\n attrs[nName] = trim(match[3]);\n }\n className = className.substr(match.index + match[0].length);\n }\n }\n break;\n case NODE_TYPE_TEXT: /* Text Node */\n addTextInterpolateDirective(directives, node.nodeValue);\n break;\n case NODE_TYPE_COMMENT: /* Comment */\n try {\n match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n if (match) {\n nName = directiveNormalize(match[1]);\n if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {\n attrs[nName] = trim(match[2]);\n }\n }\n } catch (e) {\n // turns out that under some circumstances IE9 throws errors when one attempts to read\n // comment's node value.\n // Just ignore it and continue. (Can't seem to reproduce in test case.)\n }\n break;\n }\n\n directives.sort(byPriority);\n return directives;\n }\n\n /**\n * Given a node with an directive-start it collects all of the siblings until it finds\n * directive-end.\n * @param node\n * @param attrStart\n * @param attrEnd\n * @returns {*}\n */\n function groupScan(node, attrStart, attrEnd) {\n var nodes = [];\n var depth = 0;\n if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {\n do {\n if (!node) {\n throw $compileMinErr('uterdir',\n \"Unterminated attribute, found '{0}' but no matching '{1}' found.\",\n attrStart, attrEnd);\n }\n if (node.nodeType == NODE_TYPE_ELEMENT) {\n if (node.hasAttribute(attrStart)) depth++;\n if (node.hasAttribute(attrEnd)) depth--;\n }\n nodes.push(node);\n node = node.nextSibling;\n } while (depth > 0);\n } else {\n nodes.push(node);\n }\n\n return jqLite(nodes);\n }\n\n /**\n * Wrapper for linking function which converts normal linking function into a grouped\n * linking function.\n * @param linkFn\n * @param attrStart\n * @param attrEnd\n * @returns {Function}\n */\n function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {\n return function(scope, element, attrs, controllers, transcludeFn) {\n element = groupScan(element[0], attrStart, attrEnd);\n return linkFn(scope, element, attrs, controllers, transcludeFn);\n };\n }\n\n /**\n * Once the directives have been collected, their compile functions are executed. This method\n * is responsible for inlining directive templates as well as terminating the application\n * of the directives if the terminal directive has been reached.\n *\n * @param {Array} directives Array of collected directives to execute their compile function.\n * this needs to be pre-sorted by priority order.\n * @param {Node} compileNode The raw DOM node to apply the compile functions to\n * @param {Object} templateAttrs The shared attribute function\n * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n * scope argument is auto-generated to the new\n * child of the transcluded parent scope.\n * @param {JQLite} jqCollection If we are working on the root of the compile tree then this\n * argument has the root jqLite array so that we can replace nodes\n * on it.\n * @param {Object=} originalReplaceDirective An optional directive that will be ignored when\n * compiling the transclusion.\n * @param {Array.} preLinkFns\n * @param {Array.} postLinkFns\n * @param {Object} previousCompileContext Context used for previous compilation of the current\n * node\n * @returns {Function} linkFn\n */\n function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,\n jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,\n previousCompileContext) {\n previousCompileContext = previousCompileContext || {};\n\n var terminalPriority = -Number.MAX_VALUE,\n newScopeDirective,\n controllerDirectives = previousCompileContext.controllerDirectives,\n controllers,\n newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,\n templateDirective = previousCompileContext.templateDirective,\n nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,\n hasTranscludeDirective = false,\n hasTemplate = false,\n hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,\n $compileNode = templateAttrs.$$element = jqLite(compileNode),\n directive,\n directiveName,\n $template,\n replaceDirective = originalReplaceDirective,\n childTranscludeFn = transcludeFn,\n linkFn,\n directiveValue;\n\n // executes all directives on the current element\n for (var i = 0, ii = directives.length; i < ii; i++) {\n directive = directives[i];\n var attrStart = directive.$$start;\n var attrEnd = directive.$$end;\n\n // collect multiblock sections\n if (attrStart) {\n $compileNode = groupScan(compileNode, attrStart, attrEnd);\n }\n $template = undefined;\n\n if (terminalPriority > directive.priority) {\n break; // prevent further processing of directives\n }\n\n if (directiveValue = directive.scope) {\n\n // skip the check for directives with async templates, we'll check the derived sync\n // directive when the template arrives\n if (!directive.templateUrl) {\n if (isObject(directiveValue)) {\n // This directive is trying to add an isolated scope.\n // Check that there is no scope of any kind already\n assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective,\n directive, $compileNode);\n newIsolateScopeDirective = directive;\n } else {\n // This directive is trying to add a child scope.\n // Check that there is no isolated scope already\n assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,\n $compileNode);\n }\n }\n\n newScopeDirective = newScopeDirective || directive;\n }\n\n directiveName = directive.name;\n\n if (!directive.templateUrl && directive.controller) {\n directiveValue = directive.controller;\n controllerDirectives = controllerDirectives || {};\n assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n controllerDirectives[directiveName], directive, $compileNode);\n controllerDirectives[directiveName] = directive;\n }\n\n if (directiveValue = directive.transclude) {\n hasTranscludeDirective = true;\n\n // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.\n // This option should only be used by directives that know how to safely handle element transclusion,\n // where the transcluded nodes are added or replaced after linking.\n if (!directive.$$tlb) {\n assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);\n nonTlbTranscludeDirective = directive;\n }\n\n if (directiveValue == 'element') {\n hasElementTranscludeDirective = true;\n terminalPriority = directive.priority;\n $template = $compileNode;\n $compileNode = templateAttrs.$$element =\n jqLite(document.createComment(' ' + directiveName + ': ' +\n templateAttrs[directiveName] + ' '));\n compileNode = $compileNode[0];\n replaceWith(jqCollection, sliceArgs($template), compileNode);\n\n childTranscludeFn = compile($template, transcludeFn, terminalPriority,\n replaceDirective && replaceDirective.name, {\n // Don't pass in:\n // - controllerDirectives - otherwise we'll create duplicates controllers\n // - newIsolateScopeDirective or templateDirective - combining templates with\n // element transclusion doesn't make sense.\n //\n // We need only nonTlbTranscludeDirective so that we prevent putting transclusion\n // on the same element more than once.\n nonTlbTranscludeDirective: nonTlbTranscludeDirective\n });\n } else {\n $template = jqLite(jqLiteClone(compileNode)).contents();\n $compileNode.empty(); // clear contents\n childTranscludeFn = compile($template, transcludeFn);\n }\n }\n\n if (directive.template) {\n hasTemplate = true;\n assertNoDuplicate('template', templateDirective, directive, $compileNode);\n templateDirective = directive;\n\n directiveValue = (isFunction(directive.template))\n ? directive.template($compileNode, templateAttrs)\n : directive.template;\n\n directiveValue = denormalizeTemplate(directiveValue);\n\n if (directive.replace) {\n replaceDirective = directive;\n if (jqLiteIsTextNode(directiveValue)) {\n $template = [];\n } else {\n $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue)));\n }\n compileNode = $template[0];\n\n if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {\n throw $compileMinErr('tplrt',\n \"Template for directive '{0}' must have exactly one root element. {1}\",\n directiveName, '');\n }\n\n replaceWith(jqCollection, $compileNode, compileNode);\n\n var newTemplateAttrs = {$attr: {}};\n\n // combine directives from the original node and from the template:\n // - take the array of directives for this element\n // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)\n // - collect directives from the template and sort them by priority\n // - combine directives as: processed + template + unprocessed\n var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);\n var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));\n\n if (newIsolateScopeDirective) {\n markDirectivesAsIsolate(templateDirectives);\n }\n directives = directives.concat(templateDirectives).concat(unprocessedDirectives);\n mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n ii = directives.length;\n } else {\n $compileNode.html(directiveValue);\n }\n }\n\n if (directive.templateUrl) {\n hasTemplate = true;\n assertNoDuplicate('template', templateDirective, directive, $compileNode);\n templateDirective = directive;\n\n if (directive.replace) {\n replaceDirective = directive;\n }\n\n nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,\n templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {\n controllerDirectives: controllerDirectives,\n newIsolateScopeDirective: newIsolateScopeDirective,\n templateDirective: templateDirective,\n nonTlbTranscludeDirective: nonTlbTranscludeDirective\n });\n ii = directives.length;\n } else if (directive.compile) {\n try {\n linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n if (isFunction(linkFn)) {\n addLinkFns(null, linkFn, attrStart, attrEnd);\n } else if (linkFn) {\n addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);\n }\n } catch (e) {\n $exceptionHandler(e, startingTag($compileNode));\n }\n }\n\n if (directive.terminal) {\n nodeLinkFn.terminal = true;\n terminalPriority = Math.max(terminalPriority, directive.priority);\n }\n\n }\n\n nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;\n nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;\n nodeLinkFn.elementTranscludeOnThisElement = hasElementTranscludeDirective;\n nodeLinkFn.templateOnThisElement = hasTemplate;\n nodeLinkFn.transclude = childTranscludeFn;\n\n previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;\n\n // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n return nodeLinkFn;\n\n ////////////////////\n\n function addLinkFns(pre, post, attrStart, attrEnd) {\n if (pre) {\n if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);\n pre.require = directive.require;\n pre.directiveName = directiveName;\n if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n pre = cloneAndAnnotateFn(pre, {isolateScope: true});\n }\n preLinkFns.push(pre);\n }\n if (post) {\n if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);\n post.require = directive.require;\n post.directiveName = directiveName;\n if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n post = cloneAndAnnotateFn(post, {isolateScope: true});\n }\n postLinkFns.push(post);\n }\n }\n\n\n function getControllers(directiveName, require, $element, elementControllers) {\n var value, retrievalMethod = 'data', optional = false;\n var $searchElement = $element;\n var match;\n if (isString(require)) {\n match = require.match(REQUIRE_PREFIX_REGEXP);\n require = require.substring(match[0].length);\n\n if (match[3]) {\n if (match[1]) match[3] = null;\n else match[1] = match[3];\n }\n if (match[1] === '^') {\n retrievalMethod = 'inheritedData';\n } else if (match[1] === '^^') {\n retrievalMethod = 'inheritedData';\n $searchElement = $element.parent();\n }\n if (match[2] === '?') {\n optional = true;\n }\n\n value = null;\n\n if (elementControllers && retrievalMethod === 'data') {\n if (value = elementControllers[require]) {\n value = value.instance;\n }\n }\n value = value || $searchElement[retrievalMethod]('$' + require + 'Controller');\n\n if (!value && !optional) {\n throw $compileMinErr('ctreq',\n \"Controller '{0}', required by directive '{1}', can't be found!\",\n require, directiveName);\n }\n return value || null;\n } else if (isArray(require)) {\n value = [];\n forEach(require, function(require) {\n value.push(getControllers(directiveName, require, $element, elementControllers));\n });\n }\n return value;\n }\n\n\n function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element,\n attrs;\n\n if (compileNode === linkNode) {\n attrs = templateAttrs;\n $element = templateAttrs.$$element;\n } else {\n $element = jqLite(linkNode);\n attrs = new Attributes($element, templateAttrs);\n }\n\n if (newIsolateScopeDirective) {\n isolateScope = scope.$new(true);\n }\n\n if (boundTranscludeFn) {\n // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`\n // is later passed as `parentBoundTranscludeFn` to `publicLinkFn`\n transcludeFn = controllersBoundTransclude;\n transcludeFn.$$boundTransclude = boundTranscludeFn;\n }\n\n if (controllerDirectives) {\n // TODO: merge `controllers` and `elementControllers` into single object.\n controllers = {};\n elementControllers = {};\n forEach(controllerDirectives, function(directive) {\n var locals = {\n $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,\n $element: $element,\n $attrs: attrs,\n $transclude: transcludeFn\n }, controllerInstance;\n\n controller = directive.controller;\n if (controller == '@') {\n controller = attrs[directive.name];\n }\n\n controllerInstance = $controller(controller, locals, true, directive.controllerAs);\n\n // For directives with element transclusion the element is a comment,\n // but jQuery .data doesn't support attaching data to comment nodes as it's hard to\n // clean up (http://bugs.jquery.com/ticket/8335).\n // Instead, we save the controllers for the element in a local hash and attach to .data\n // later, once we have the actual element.\n elementControllers[directive.name] = controllerInstance;\n if (!hasElementTranscludeDirective) {\n $element.data('$' + directive.name + 'Controller', controllerInstance.instance);\n }\n\n controllers[directive.name] = controllerInstance;\n });\n }\n\n if (newIsolateScopeDirective) {\n compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||\n templateDirective === newIsolateScopeDirective.$$originalDirective)));\n compile.$$addScopeClass($element, true);\n\n var isolateScopeController = controllers && controllers[newIsolateScopeDirective.name];\n var isolateBindingContext = isolateScope;\n if (isolateScopeController && isolateScopeController.identifier &&\n newIsolateScopeDirective.bindToController === true) {\n isolateBindingContext = isolateScopeController.instance;\n }\n\n forEach(isolateScope.$$isolateBindings = newIsolateScopeDirective.$$isolateBindings, function(definition, scopeName) {\n var attrName = definition.attrName,\n optional = definition.optional,\n mode = definition.mode, // @, =, or &\n lastValue,\n parentGet, parentSet, compare;\n\n switch (mode) {\n\n case '@':\n attrs.$observe(attrName, function(value) {\n isolateBindingContext[scopeName] = value;\n });\n attrs.$$observers[attrName].$$scope = scope;\n if (attrs[attrName]) {\n // If the attribute has been provided then we trigger an interpolation to ensure\n // the value is there for use in the link fn\n isolateBindingContext[scopeName] = $interpolate(attrs[attrName])(scope);\n }\n break;\n\n case '=':\n if (optional && !attrs[attrName]) {\n return;\n }\n parentGet = $parse(attrs[attrName]);\n if (parentGet.literal) {\n compare = equals;\n } else {\n compare = function(a, b) { return a === b || (a !== a && b !== b); };\n }\n parentSet = parentGet.assign || function() {\n // reset the change, or we will throw this exception on every $digest\n lastValue = isolateBindingContext[scopeName] = parentGet(scope);\n throw $compileMinErr('nonassign',\n \"Expression '{0}' used with directive '{1}' is non-assignable!\",\n attrs[attrName], newIsolateScopeDirective.name);\n };\n lastValue = isolateBindingContext[scopeName] = parentGet(scope);\n var parentValueWatch = function parentValueWatch(parentValue) {\n if (!compare(parentValue, isolateBindingContext[scopeName])) {\n // we are out of sync and need to copy\n if (!compare(parentValue, lastValue)) {\n // parent changed and it has precedence\n isolateBindingContext[scopeName] = parentValue;\n } else {\n // if the parent can be assigned then do so\n parentSet(scope, parentValue = isolateBindingContext[scopeName]);\n }\n }\n return lastValue = parentValue;\n };\n parentValueWatch.$stateful = true;\n var unwatch;\n if (definition.collection) {\n unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch);\n } else {\n unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);\n }\n isolateScope.$on('$destroy', unwatch);\n break;\n\n case '&':\n parentGet = $parse(attrs[attrName]);\n isolateBindingContext[scopeName] = function(locals) {\n return parentGet(scope, locals);\n };\n break;\n }\n });\n }\n if (controllers) {\n forEach(controllers, function(controller) {\n controller();\n });\n controllers = null;\n }\n\n // PRELINKING\n for (i = 0, ii = preLinkFns.length; i < ii; i++) {\n linkFn = preLinkFns[i];\n invokeLinkFn(linkFn,\n linkFn.isolateScope ? isolateScope : scope,\n $element,\n attrs,\n linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),\n transcludeFn\n );\n }\n\n // RECURSION\n // We only pass the isolate scope, if the isolate directive has a template,\n // otherwise the child elements do not belong to the isolate directive.\n var scopeToChild = scope;\n if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {\n scopeToChild = isolateScope;\n }\n childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);\n\n // POSTLINKING\n for (i = postLinkFns.length - 1; i >= 0; i--) {\n linkFn = postLinkFns[i];\n invokeLinkFn(linkFn,\n linkFn.isolateScope ? isolateScope : scope,\n $element,\n attrs,\n linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),\n transcludeFn\n );\n }\n\n // This is the function that is injected as `$transclude`.\n // Note: all arguments are optional!\n function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) {\n var transcludeControllers;\n\n // No scope passed in:\n if (!isScope(scope)) {\n futureParentElement = cloneAttachFn;\n cloneAttachFn = scope;\n scope = undefined;\n }\n\n if (hasElementTranscludeDirective) {\n transcludeControllers = elementControllers;\n }\n if (!futureParentElement) {\n futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;\n }\n return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);\n }\n }\n }\n\n function markDirectivesAsIsolate(directives) {\n // mark all directives as needing isolate scope.\n for (var j = 0, jj = directives.length; j < jj; j++) {\n directives[j] = inherit(directives[j], {$$isolateScope: true});\n }\n }\n\n /**\n * looks up the directive and decorates it with exception handling and proper parameters. We\n * call this the boundDirective.\n *\n * @param {string} name name of the directive to look up.\n * @param {string} location The directive must be found in specific format.\n * String containing any of theses characters:\n *\n * * `E`: element name\n * * `A': attribute\n * * `C`: class\n * * `M`: comment\n * @returns {boolean} true if directive was added.\n */\n function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,\n endAttrName) {\n if (name === ignoreDirective) return null;\n var match = null;\n if (hasDirectives.hasOwnProperty(name)) {\n for (var directive, directives = $injector.get(name + Suffix),\n i = 0, ii = directives.length; i < ii; i++) {\n try {\n directive = directives[i];\n if ((maxPriority === undefined || maxPriority > directive.priority) &&\n directive.restrict.indexOf(location) != -1) {\n if (startAttrName) {\n directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});\n }\n tDirectives.push(directive);\n match = directive;\n }\n } catch (e) { $exceptionHandler(e); }\n }\n }\n return match;\n }\n\n\n /**\n * looks up the directive and returns true if it is a multi-element directive,\n * and therefore requires DOM nodes between -start and -end markers to be grouped\n * together.\n *\n * @param {string} name name of the directive to look up.\n * @returns true if directive was registered as multi-element.\n */\n function directiveIsMultiElement(name) {\n if (hasDirectives.hasOwnProperty(name)) {\n for (var directive, directives = $injector.get(name + Suffix),\n i = 0, ii = directives.length; i < ii; i++) {\n directive = directives[i];\n if (directive.multiElement) {\n return true;\n }\n }\n }\n return false;\n }\n\n /**\n * When the element is replaced with HTML template then the new attributes\n * on the template need to be merged with the existing attributes in the DOM.\n * The desired effect is to have both of the attributes present.\n *\n * @param {object} dst destination attributes (original DOM)\n * @param {object} src source attributes (from the directive template)\n */\n function mergeTemplateAttributes(dst, src) {\n var srcAttr = src.$attr,\n dstAttr = dst.$attr,\n $element = dst.$$element;\n\n // reapply the old attributes to the new element\n forEach(dst, function(value, key) {\n if (key.charAt(0) != '$') {\n if (src[key] && src[key] !== value) {\n value += (key === 'style' ? ';' : ' ') + src[key];\n }\n dst.$set(key, value, true, srcAttr[key]);\n }\n });\n\n // copy the new attributes on the old attrs object\n forEach(src, function(value, key) {\n if (key == 'class') {\n safeAddClass($element, value);\n dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n } else if (key == 'style') {\n $element.attr('style', $element.attr('style') + ';' + value);\n dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;\n // `dst` will never contain hasOwnProperty as DOM parser won't let it.\n // You will get an \"InvalidCharacterError: DOM Exception 5\" error if you\n // have an attribute like \"has-own-property\" or \"data-has-own-property\", etc.\n } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n dst[key] = value;\n dstAttr[key] = srcAttr[key];\n }\n });\n }\n\n\n function compileTemplateUrl(directives, $compileNode, tAttrs,\n $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {\n var linkQueue = [],\n afterTemplateNodeLinkFn,\n afterTemplateChildLinkFn,\n beforeTemplateCompileNode = $compileNode[0],\n origAsyncDirective = directives.shift(),\n // The fact that we have to copy and patch the directive seems wrong!\n derivedSyncDirective = extend({}, origAsyncDirective, {\n templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective\n }),\n templateUrl = (isFunction(origAsyncDirective.templateUrl))\n ? origAsyncDirective.templateUrl($compileNode, tAttrs)\n : origAsyncDirective.templateUrl,\n templateNamespace = origAsyncDirective.templateNamespace;\n\n $compileNode.empty();\n\n $templateRequest($sce.getTrustedResourceUrl(templateUrl))\n .then(function(content) {\n var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;\n\n content = denormalizeTemplate(content);\n\n if (origAsyncDirective.replace) {\n if (jqLiteIsTextNode(content)) {\n $template = [];\n } else {\n $template = removeComments(wrapTemplate(templateNamespace, trim(content)));\n }\n compileNode = $template[0];\n\n if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {\n throw $compileMinErr('tplrt',\n \"Template for directive '{0}' must have exactly one root element. {1}\",\n origAsyncDirective.name, templateUrl);\n }\n\n tempTemplateAttrs = {$attr: {}};\n replaceWith($rootElement, $compileNode, compileNode);\n var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);\n\n if (isObject(origAsyncDirective.scope)) {\n markDirectivesAsIsolate(templateDirectives);\n }\n directives = templateDirectives.concat(directives);\n mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n } else {\n compileNode = beforeTemplateCompileNode;\n $compileNode.html(content);\n }\n\n directives.unshift(derivedSyncDirective);\n\n afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,\n childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,\n previousCompileContext);\n forEach($rootElement, function(node, i) {\n if (node == compileNode) {\n $rootElement[i] = $compileNode[0];\n }\n });\n afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);\n\n while (linkQueue.length) {\n var scope = linkQueue.shift(),\n beforeTemplateLinkNode = linkQueue.shift(),\n linkRootElement = linkQueue.shift(),\n boundTranscludeFn = linkQueue.shift(),\n linkNode = $compileNode[0];\n\n if (scope.$$destroyed) continue;\n\n if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n var oldClasses = beforeTemplateLinkNode.className;\n\n if (!(previousCompileContext.hasElementTranscludeDirective &&\n origAsyncDirective.replace)) {\n // it was cloned therefore we have to clone as well.\n linkNode = jqLiteClone(compileNode);\n }\n replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n\n // Copy in CSS classes from original node\n safeAddClass(jqLite(linkNode), oldClasses);\n }\n if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n } else {\n childBoundTranscludeFn = boundTranscludeFn;\n }\n afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,\n childBoundTranscludeFn);\n }\n linkQueue = null;\n });\n\n return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {\n var childBoundTranscludeFn = boundTranscludeFn;\n if (scope.$$destroyed) return;\n if (linkQueue) {\n linkQueue.push(scope,\n node,\n rootElement,\n childBoundTranscludeFn);\n } else {\n if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n }\n afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);\n }\n };\n }\n\n\n /**\n * Sorting function for bound directives.\n */\n function byPriority(a, b) {\n var diff = b.priority - a.priority;\n if (diff !== 0) return diff;\n if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;\n return a.index - b.index;\n }\n\n\n function assertNoDuplicate(what, previousDirective, directive, element) {\n if (previousDirective) {\n throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}',\n previousDirective.name, directive.name, what, startingTag(element));\n }\n }\n\n\n function addTextInterpolateDirective(directives, text) {\n var interpolateFn = $interpolate(text, true);\n if (interpolateFn) {\n directives.push({\n priority: 0,\n compile: function textInterpolateCompileFn(templateNode) {\n var templateNodeParent = templateNode.parent(),\n hasCompileParent = !!templateNodeParent.length;\n\n // When transcluding a template that has bindings in the root\n // we don't have a parent and thus need to add the class during linking fn.\n if (hasCompileParent) compile.$$addBindingClass(templateNodeParent);\n\n return function textInterpolateLinkFn(scope, node) {\n var parent = node.parent();\n if (!hasCompileParent) compile.$$addBindingClass(parent);\n compile.$$addBindingInfo(parent, interpolateFn.expressions);\n scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n node[0].nodeValue = value;\n });\n };\n }\n });\n }\n }\n\n\n function wrapTemplate(type, template) {\n type = lowercase(type || 'html');\n switch (type) {\n case 'svg':\n case 'math':\n var wrapper = document.createElement('div');\n wrapper.innerHTML = '<' + type + '>' + template + '';\n return wrapper.childNodes[0].childNodes;\n default:\n return template;\n }\n }\n\n\n function getTrustedContext(node, attrNormalizedName) {\n if (attrNormalizedName == \"srcdoc\") {\n return $sce.HTML;\n }\n var tag = nodeName_(node);\n // maction[xlink:href] can source SVG. It's not limited to .\n if (attrNormalizedName == \"xlinkHref\" ||\n (tag == \"form\" && attrNormalizedName == \"action\") ||\n (tag != \"img\" && (attrNormalizedName == \"src\" ||\n attrNormalizedName == \"ngSrc\"))) {\n return $sce.RESOURCE_URL;\n }\n }\n\n\n function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {\n var trustedContext = getTrustedContext(node, name);\n allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;\n\n var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);\n\n // no interpolation found -> ignore\n if (!interpolateFn) return;\n\n\n if (name === \"multiple\" && nodeName_(node) === \"select\") {\n throw $compileMinErr(\"selmulti\",\n \"Binding to the 'multiple' attribute is not supported. Element: {0}\",\n startingTag(node));\n }\n\n directives.push({\n priority: 100,\n compile: function() {\n return {\n pre: function attrInterpolatePreLinkFn(scope, element, attr) {\n var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {\n throw $compileMinErr('nodomevents',\n \"Interpolations for HTML DOM event attributes are disallowed. Please use the \" +\n \"ng- versions (such as ng-click instead of onclick) instead.\");\n }\n\n // If the attribute has changed since last $interpolate()ed\n var newValue = attr[name];\n if (newValue !== value) {\n // we need to interpolate again since the attribute value has been updated\n // (e.g. by another directive's compile function)\n // ensure unset/empty values make interpolateFn falsy\n interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);\n value = newValue;\n }\n\n // if attribute was updated so that there is no interpolation going on we don't want to\n // register any observers\n if (!interpolateFn) return;\n\n // initialize attr object so that it's ready in case we need the value for isolate\n // scope initialization, otherwise the value would not be available from isolate\n // directive's linking fn during linking phase\n attr[name] = interpolateFn(scope);\n\n ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n (attr.$$observers && attr.$$observers[name].$$scope || scope).\n $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {\n //special case for class attribute addition + removal\n //so that class changes can tap into the animation\n //hooks provided by the $animate service. Be sure to\n //skip animations when the first digest occurs (when\n //both the new and the old values are the same) since\n //the CSS classes are the non-interpolated values\n if (name === 'class' && newValue != oldValue) {\n attr.$updateClass(newValue, oldValue);\n } else {\n attr.$set(name, newValue);\n }\n });\n }\n };\n }\n });\n }\n\n\n /**\n * This is a special jqLite.replaceWith, which can replace items which\n * have no parents, provided that the containing jqLite collection is provided.\n *\n * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n * in the root of the tree.\n * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep\n * the shell, but replace its DOM node reference.\n * @param {Node} newNode The new DOM node.\n */\n function replaceWith($rootElement, elementsToRemove, newNode) {\n var firstElementToRemove = elementsToRemove[0],\n removeCount = elementsToRemove.length,\n parent = firstElementToRemove.parentNode,\n i, ii;\n\n if ($rootElement) {\n for (i = 0, ii = $rootElement.length; i < ii; i++) {\n if ($rootElement[i] == firstElementToRemove) {\n $rootElement[i++] = newNode;\n for (var j = i, j2 = j + removeCount - 1,\n jj = $rootElement.length;\n j < jj; j++, j2++) {\n if (j2 < jj) {\n $rootElement[j] = $rootElement[j2];\n } else {\n delete $rootElement[j];\n }\n }\n $rootElement.length -= removeCount - 1;\n\n // If the replaced element is also the jQuery .context then replace it\n // .context is a deprecated jQuery api, so we should set it only when jQuery set it\n // http://api.jquery.com/context/\n if ($rootElement.context === firstElementToRemove) {\n $rootElement.context = newNode;\n }\n break;\n }\n }\n }\n\n if (parent) {\n parent.replaceChild(newNode, firstElementToRemove);\n }\n\n // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it?\n var fragment = document.createDocumentFragment();\n fragment.appendChild(firstElementToRemove);\n\n // Copy over user data (that includes Angular's $scope etc.). Don't copy private\n // data here because there's no public interface in jQuery to do that and copying over\n // event listeners (which is the main use of private data) wouldn't work anyway.\n jqLite(newNode).data(jqLite(firstElementToRemove).data());\n\n // Remove data of the replaced element. We cannot just call .remove()\n // on the element it since that would deallocate scope that is needed\n // for the new node. Instead, remove the data \"manually\".\n if (!jQuery) {\n delete jqLite.cache[firstElementToRemove[jqLite.expando]];\n } else {\n // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after\n // the replaced element. The cleanData version monkey-patched by Angular would cause\n // the scope to be trashed and we do need the very same scope to work with the new\n // element. However, we cannot just cache the non-patched version and use it here as\n // that would break if another library patches the method after Angular does (one\n // example is jQuery UI). Instead, set a flag indicating scope destroying should be\n // skipped this one time.\n skipDestroyOnNextJQueryCleanData = true;\n jQuery.cleanData([firstElementToRemove]);\n }\n\n for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {\n var element = elementsToRemove[k];\n jqLite(element).remove(); // must do this way to clean up expando\n fragment.appendChild(element);\n delete elementsToRemove[k];\n }\n\n elementsToRemove[0] = newNode;\n elementsToRemove.length = 1;\n }\n\n\n function cloneAndAnnotateFn(fn, annotation) {\n return extend(function() { return fn.apply(null, arguments); }, fn, annotation);\n }\n\n\n function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {\n try {\n linkFn(scope, $element, attrs, controllers, transcludeFn);\n } catch (e) {\n $exceptionHandler(e, startingTag($element));\n }\n }\n }];\n}\n\nvar PREFIX_REGEXP = /^((?:x|data)[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc type\n * @name $compile.directive.Attributes\n *\n * @description\n * A shared object between directive compile / linking functions which contains normalized DOM\n * element attributes. The values reflect current binding state `{{ }}`. The normalization is\n * needed since all of these are treated as equivalent in Angular:\n *\n * ```\n * \n * ```\n */\n\n/**\n * @ngdoc property\n * @name $compile.directive.Attributes#$attr\n *\n * @description\n * A map of DOM element attribute names to the normalized name. This is\n * needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc method\n * @name $compile.directive.Attributes#$set\n * @kind function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n * reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n * property to the original name.\n * @param {string} value Value to set the attribute to. The value can be an interpolated string.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n /* angular.Scope */ scope,\n /* NodeList */ nodeList,\n /* Element */ rootElement,\n /* function(Function) */ boundTranscludeFn\n) {}\n\nfunction directiveLinkingFn(\n /* nodesetLinkingFn */ nodesetLinkingFn,\n /* angular.Scope */ scope,\n /* Node */ node,\n /* Element */ rootElement,\n /* function(Function) */ boundTranscludeFn\n) {}\n\nfunction tokenDifference(str1, str2) {\n var values = '',\n tokens1 = str1.split(/\\s+/),\n tokens2 = str2.split(/\\s+/);\n\n outer:\n for (var i = 0; i < tokens1.length; i++) {\n var token = tokens1[i];\n for (var j = 0; j < tokens2.length; j++) {\n if (token == tokens2[j]) continue outer;\n }\n values += (values.length > 0 ? ' ' : '') + token;\n }\n return values;\n}\n\nfunction removeComments(jqNodes) {\n jqNodes = jqLite(jqNodes);\n var i = jqNodes.length;\n\n if (i <= 1) {\n return jqNodes;\n }\n\n while (i--) {\n var node = jqNodes[i];\n if (node.nodeType === NODE_TYPE_COMMENT) {\n splice.call(jqNodes, i, 1);\n }\n }\n return jqNodes;\n}\n\n/**\n * @ngdoc provider\n * @name $controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n var controllers = {},\n globals = false,\n CNTRL_REG = /^(\\S+)(\\s+as\\s+(\\w+))?$/;\n\n\n /**\n * @ngdoc method\n * @name $controllerProvider#register\n * @param {string|Object} name Controller name, or an object map of controllers where the keys are\n * the names and the values are the constructors.\n * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n * annotations in the array notation).\n */\n this.register = function(name, constructor) {\n assertNotHasOwnProperty(name, 'controller');\n if (isObject(name)) {\n extend(controllers, name);\n } else {\n controllers[name] = constructor;\n }\n };\n\n /**\n * @ngdoc method\n * @name $controllerProvider#allowGlobals\n * @description If called, allows `$controller` to find controller constructors on `window`\n */\n this.allowGlobals = function() {\n globals = true;\n };\n\n\n this.$get = ['$injector', '$window', function($injector, $window) {\n\n /**\n * @ngdoc service\n * @name $controller\n * @requires $injector\n *\n * @param {Function|string} constructor If called with a function then it's considered to be the\n * controller constructor function. Otherwise it's considered to be a string which is used\n * to retrieve the controller constructor using the following steps:\n *\n * * check if a controller with given name is registered via `$controllerProvider`\n * * check if evaluating the string on the current scope returns a constructor\n * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global\n * `window` object (not recommended)\n *\n * The string can use the `controller as property` syntax, where the controller instance is published\n * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this\n * to work correctly.\n *\n * @param {Object} locals Injection locals for Controller.\n * @return {Object} Instance of given controller.\n *\n * @description\n * `$controller` service is responsible for instantiating controllers.\n *\n * It's just a simple call to {@link auto.$injector $injector}, but extracted into\n * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).\n */\n return function(expression, locals, later, ident) {\n // PRIVATE API:\n // param `later` --- indicates that the controller's constructor is invoked at a later time.\n // If true, $controller will allocate the object with the correct\n // prototype chain, but will not invoke the controller until a returned\n // callback is invoked.\n // param `ident` --- An optional label which overrides the label parsed from the controller\n // expression, if any.\n var instance, match, constructor, identifier;\n later = later === true;\n if (ident && isString(ident)) {\n identifier = ident;\n }\n\n if (isString(expression)) {\n match = expression.match(CNTRL_REG),\n constructor = match[1],\n identifier = identifier || match[3];\n expression = controllers.hasOwnProperty(constructor)\n ? controllers[constructor]\n : getter(locals.$scope, constructor, true) ||\n (globals ? getter($window, constructor, true) : undefined);\n\n assertArgFn(expression, constructor, true);\n }\n\n if (later) {\n // Instantiate controller later:\n // This machinery is used to create an instance of the object before calling the\n // controller's constructor itself.\n //\n // This allows properties to be added to the controller before the constructor is\n // invoked. Primarily, this is used for isolate scope bindings in $compile.\n //\n // This feature is not intended for use by applications, and is thus not documented\n // publicly.\n // Object creation: http://jsperf.com/create-constructor/2\n var controllerPrototype = (isArray(expression) ?\n expression[expression.length - 1] : expression).prototype;\n instance = Object.create(controllerPrototype || null);\n\n if (identifier) {\n addIdentifier(locals, identifier, instance, constructor || expression.name);\n }\n\n return extend(function() {\n $injector.invoke(expression, instance, locals, constructor);\n return instance;\n }, {\n instance: instance,\n identifier: identifier\n });\n }\n\n instance = $injector.instantiate(expression, locals, constructor);\n\n if (identifier) {\n addIdentifier(locals, identifier, instance, constructor || expression.name);\n }\n\n return instance;\n };\n\n function addIdentifier(locals, identifier, instance, name) {\n if (!(locals && isObject(locals.$scope))) {\n throw minErr('$controller')('noscp',\n \"Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.\",\n name, identifier);\n }\n\n locals.$scope[identifier] = instance;\n }\n }];\n}\n\n/**\n * @ngdoc service\n * @name $document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.\n *\n * @example\n \n \n
\n

$document title:

\n

window.document title:

\n
\n
\n \n angular.module('documentExample', [])\n .controller('ExampleController', ['$scope', '$document', function($scope, $document) {\n $scope.title = $document[0].title;\n $scope.windowTitle = angular.element(window.document)[0].title;\n }]);\n \n
\n */\nfunction $DocumentProvider() {\n this.$get = ['$window', function(window) {\n return jqLite(window.document);\n }];\n}\n\n/**\n * @ngdoc service\n * @name $exceptionHandler\n * @requires ng.$log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * ## Example:\n *\n * ```js\n * angular.module('exceptionOverride', []).factory('$exceptionHandler', function() {\n * return function(exception, cause) {\n * exception.message += ' (caused by \"' + cause + '\")';\n * throw exception;\n * };\n * });\n * ```\n *\n * This example will override the normal action of `$exceptionHandler`, to make angular\n * exceptions fail hard when they happen, instead of just logging to the console.\n *\n *
\n * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind`\n * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler}\n * (unless executed during a digest).\n *\n * If you wish, you can manually delegate exceptions, e.g.\n * `try { ... } catch(e) { $exceptionHandler(e); }`\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n * the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n this.$get = ['$log', function($log) {\n return function(exception, cause) {\n $log.error.apply($log, arguments);\n };\n }];\n}\n\nvar APPLICATION_JSON = 'application/json';\nvar CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};\nvar JSON_START = /^\\[|^\\{(?!\\{)/;\nvar JSON_ENDS = {\n '[': /]$/,\n '{': /}$/\n};\nvar JSON_PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/;\n\nfunction defaultHttpResponseTransform(data, headers) {\n if (isString(data)) {\n // Strip json vulnerability protection prefix and trim whitespace\n var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();\n\n if (tempData) {\n var contentType = headers('Content-Type');\n if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {\n data = fromJson(tempData);\n }\n }\n }\n\n return data;\n}\n\nfunction isJsonLike(str) {\n var jsonStart = str.match(JSON_START);\n return jsonStart && JSON_ENDS[jsonStart[0]].test(str);\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n var parsed = createMap(), key, val, i;\n\n if (!headers) return parsed;\n\n forEach(headers.split('\\n'), function(line) {\n i = line.indexOf(':');\n key = lowercase(trim(line.substr(0, i)));\n val = trim(line.substr(i + 1));\n\n if (key) {\n parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;\n }\n });\n\n return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n * - if called with single an argument returns a single header value or null\n * - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n var headersObj = isObject(headers) ? headers : undefined;\n\n return function(name) {\n if (!headersObj) headersObj = parseHeaders(headers);\n\n if (name) {\n var value = headersObj[lowercase(name)];\n if (value === void 0) {\n value = null;\n }\n return value;\n }\n\n return headersObj;\n };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers HTTP headers getter fn.\n * @param {number} status HTTP status code of the response.\n * @param {(Function|Array.)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, status, fns) {\n if (isFunction(fns))\n return fns(data, headers, status);\n\n forEach(fns, function(fn) {\n data = fn(data, headers, status);\n });\n\n return data;\n}\n\n\nfunction isSuccess(status) {\n return 200 <= status && status < 300;\n}\n\n\n/**\n * @ngdoc provider\n * @name $httpProvider\n * @description\n * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.\n * */\nfunction $HttpProvider() {\n /**\n * @ngdoc property\n * @name $httpProvider#defaults\n * @description\n *\n * Object containing default values for all {@link ng.$http $http} requests.\n *\n * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`}\n * that will provide the cache for all requests who set their `cache` property to `true`.\n * If you set the `default.cache = false` then only requests that specify their own custom\n * cache object will be cached. See {@link $http#caching $http Caching} for more information.\n *\n * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.\n * Defaults value is `'XSRF-TOKEN'`.\n *\n * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the\n * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.\n *\n * - **`defaults.headers`** - {Object} - Default headers for all $http requests.\n * Refer to {@link ng.$http#setting-http-headers $http} for documentation on\n * setting default headers.\n * - **`defaults.headers.common`**\n * - **`defaults.headers.post`**\n * - **`defaults.headers.put`**\n * - **`defaults.headers.patch`**\n *\n **/\n var defaults = this.defaults = {\n // transform incoming response data\n transformResponse: [defaultHttpResponseTransform],\n\n // transform outgoing request data\n transformRequest: [function(d) {\n return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;\n }],\n\n // default headers\n headers: {\n common: {\n 'Accept': 'application/json, text/plain, */*'\n },\n post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON)\n },\n\n xsrfCookieName: 'XSRF-TOKEN',\n xsrfHeaderName: 'X-XSRF-TOKEN'\n };\n\n var useApplyAsync = false;\n /**\n * @ngdoc method\n * @name $httpProvider#useApplyAsync\n * @description\n *\n * Configure $http service to combine processing of multiple http responses received at around\n * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in\n * significant performance improvement for bigger applications that make many HTTP requests\n * concurrently (common during application bootstrap).\n *\n * Defaults to false. If no value is specifed, returns the current configured value.\n *\n * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred\n * \"apply\" on the next tick, giving time for subsequent requests in a roughly ~10ms window\n * to load and share the same digest cycle.\n *\n * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.\n * otherwise, returns the current configured value.\n **/\n this.useApplyAsync = function(value) {\n if (isDefined(value)) {\n useApplyAsync = !!value;\n return this;\n }\n return useApplyAsync;\n };\n\n /**\n * @ngdoc property\n * @name $httpProvider#interceptors\n * @description\n *\n * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}\n * pre-processing of request or postprocessing of responses.\n *\n * These service factories are ordered by request, i.e. they are applied in the same order as the\n * array, on request, but reverse order, on response.\n *\n * {@link ng.$http#interceptors Interceptors detailed info}\n **/\n var interceptorFactories = this.interceptors = [];\n\n this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n var defaultCache = $cacheFactory('$http');\n\n /**\n * Interceptors stored in reverse order. Inner interceptors before outer interceptors.\n * The reversal is needed so that we can build up the interception chain around the\n * server request.\n */\n var reversedInterceptors = [];\n\n forEach(interceptorFactories, function(interceptorFactory) {\n reversedInterceptors.unshift(isString(interceptorFactory)\n ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));\n });\n\n /**\n * @ngdoc service\n * @kind function\n * @name $http\n * @requires ng.$httpBackend\n * @requires $cacheFactory\n * @requires $rootScope\n * @requires $q\n * @requires $injector\n *\n * @description\n * The `$http` service is a core Angular service that facilitates communication with the remote\n * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)\n * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).\n *\n * For unit testing applications that use `$http` service, see\n * {@link ngMock.$httpBackend $httpBackend mock}.\n *\n * For a higher level of abstraction, please check out the {@link ngResource.$resource\n * $resource} service.\n *\n * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage\n * it is important to familiarize yourself with these APIs and the guarantees they provide.\n *\n *\n * ## General usage\n * The `$http` service is a function which takes a single argument — a configuration object —\n * that is used to generate an HTTP request and returns a {@link ng.$q promise}\n * with two $http specific methods: `success` and `error`.\n *\n * ```js\n * // Simple GET request example :\n * $http.get('/someUrl').\n * success(function(data, status, headers, config) {\n * // this callback will be called asynchronously\n * // when the response is available\n * }).\n * error(function(data, status, headers, config) {\n * // called asynchronously if an error occurs\n * // or server returns response with an error status.\n * });\n * ```\n *\n * ```js\n * // Simple POST request example (passing data) :\n * $http.post('/someUrl', {msg:'hello word!'}).\n * success(function(data, status, headers, config) {\n * // this callback will be called asynchronously\n * // when the response is available\n * }).\n * error(function(data, status, headers, config) {\n * // called asynchronously if an error occurs\n * // or server returns response with an error status.\n * });\n * ```\n *\n *\n * Since the returned value of calling the $http function is a `promise`, you can also use\n * the `then` method to register callbacks, and these callbacks will receive a single argument –\n * an object representing the response. See the API signature and type info below for more\n * details.\n *\n * A response status code between 200 and 299 is considered a success status and\n * will result in the success callback being called. Note that if the response is a redirect,\n * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n * called for such responses.\n *\n * ## Writing Unit Tests that use $http\n * When unit testing (using {@link ngMock ngMock}), it is necessary to call\n * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending\n * request using trained responses.\n *\n * ```\n * $httpBackend.expectGET(...);\n * $http.get(...);\n * $httpBackend.flush();\n * ```\n *\n * ## Shortcut methods\n *\n * Shortcut methods are also available. All shortcut methods require passing in the URL, and\n * request data must be passed in for POST/PUT requests.\n *\n * ```js\n * $http.get('/someUrl').success(successCallback);\n * $http.post('/someUrl', data).success(successCallback);\n * ```\n *\n * Complete list of shortcut methods:\n *\n * - {@link ng.$http#get $http.get}\n * - {@link ng.$http#head $http.head}\n * - {@link ng.$http#post $http.post}\n * - {@link ng.$http#put $http.put}\n * - {@link ng.$http#delete $http.delete}\n * - {@link ng.$http#jsonp $http.jsonp}\n * - {@link ng.$http#patch $http.patch}\n *\n *\n * ## Setting HTTP Headers\n *\n * The $http service will automatically add certain HTTP headers to all requests. These defaults\n * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n * object, which currently contains this default configuration:\n *\n * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n * - `Accept: application/json, text/plain, * / *`\n * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)\n * - `Content-Type: application/json`\n * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)\n * - `Content-Type: application/json`\n *\n * To add or overwrite these defaults, simply add or remove a property from these configuration\n * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n * with the lowercased HTTP method name as the key, e.g.\n * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }.\n *\n * The defaults can also be set at runtime via the `$http.defaults` object in the same\n * fashion. For example:\n *\n * ```\n * module.run(function($http) {\n * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'\n * });\n * ```\n *\n * In addition, you can supply a `headers` property in the config object passed when\n * calling `$http(config)`, which overrides the defaults without changing them globally.\n *\n * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,\n * Use the `headers` property, setting the desired header to `undefined`. For example:\n *\n * ```js\n * var req = {\n * method: 'POST',\n * url: 'http://example.com',\n * headers: {\n * 'Content-Type': undefined\n * },\n * data: { test: 'test' },\n * }\n *\n * $http(req).success(function(){...}).error(function(){...});\n * ```\n *\n * ## Transforming Requests and Responses\n *\n * Both requests and responses can be transformed using transformation functions: `transformRequest`\n * and `transformResponse`. These properties can be a single function that returns\n * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions,\n * which allows you to `push` or `unshift` a new transformation function into the transformation chain.\n *\n * ### Default Transformations\n *\n * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and\n * `defaults.transformResponse` properties. If a request does not provide its own transformations\n * then these will be applied.\n *\n * You can augment or replace the default transformations by modifying these properties by adding to or\n * replacing the array.\n *\n * Angular provides the following default transformations:\n *\n * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`):\n *\n * - If the `data` property of the request configuration object contains an object, serialize it\n * into JSON format.\n *\n * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`):\n *\n * - If XSRF prefix is detected, strip it (see Security Considerations section below).\n * - If JSON response is detected, deserialize it using a JSON parser.\n *\n *\n * ### Overriding the Default Transformations Per Request\n *\n * If you wish override the request/response transformations only for a single request then provide\n * `transformRequest` and/or `transformResponse` properties on the configuration object passed\n * into `$http`.\n *\n * Note that if you provide these properties on the config object the default transformations will be\n * overwritten. If you wish to augment the default transformations then you must include them in your\n * local transformation array.\n *\n * The following code demonstrates adding a new response transformation to be run after the default response\n * transformations have been run.\n *\n * ```js\n * function appendTransform(defaults, transform) {\n *\n * // We can't guarantee that the default transformation is an array\n * defaults = angular.isArray(defaults) ? defaults : [defaults];\n *\n * // Append the new transformation to the defaults\n * return defaults.concat(transform);\n * }\n *\n * $http({\n * url: '...',\n * method: 'GET',\n * transformResponse: appendTransform($http.defaults.transformResponse, function(value) {\n * return doTransform(value);\n * })\n * });\n * ```\n *\n *\n * ## Caching\n *\n * To enable caching, set the request configuration `cache` property to `true` (to use default\n * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).\n * When the cache is enabled, `$http` stores the response from the server in the specified\n * cache. The next time the same request is made, the response is served from the cache without\n * sending a request to the server.\n *\n * Note that even if the response is served from cache, delivery of the data is asynchronous in\n * the same way that real requests are.\n *\n * If there are multiple GET requests for the same URL that should be cached using the same\n * cache, but the cache is not populated yet, only one request to the server will be made and\n * the remaining requests will be fulfilled using the response from the first request.\n *\n * You can change the default cache to a new object (built with\n * {@link ng.$cacheFactory `$cacheFactory`}) by updating the\n * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set\n * their `cache` property to `true` will now use this cache object.\n *\n * If you set the default cache to `false` then only requests that specify their own custom\n * cache object will be cached.\n *\n * ## Interceptors\n *\n * Before you start creating interceptors, be sure to understand the\n * {@link ng.$q $q and deferred/promise APIs}.\n *\n * For purposes of global error handling, authentication, or any kind of synchronous or\n * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be\n * able to intercept requests before they are handed to the server and\n * responses before they are handed over to the application code that\n * initiated these requests. The interceptors leverage the {@link ng.$q\n * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.\n *\n * The interceptors are service factories that are registered with the `$httpProvider` by\n * adding them to the `$httpProvider.interceptors` array. The factory is called and\n * injected with dependencies (if specified) and returns the interceptor.\n *\n * There are two kinds of interceptors (and two kinds of rejection interceptors):\n *\n * * `request`: interceptors get called with a http `config` object. The function is free to\n * modify the `config` object or create a new one. The function needs to return the `config`\n * object directly, or a promise containing the `config` or a new `config` object.\n * * `requestError`: interceptor gets called when a previous interceptor threw an error or\n * resolved with a rejection.\n * * `response`: interceptors get called with http `response` object. The function is free to\n * modify the `response` object or create a new one. The function needs to return the `response`\n * object directly, or as a promise containing the `response` or a new `response` object.\n * * `responseError`: interceptor gets called when a previous interceptor threw an error or\n * resolved with a rejection.\n *\n *\n * ```js\n * // register the interceptor as a service\n * $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n * return {\n * // optional method\n * 'request': function(config) {\n * // do something on success\n * return config;\n * },\n *\n * // optional method\n * 'requestError': function(rejection) {\n * // do something on error\n * if (canRecover(rejection)) {\n * return responseOrNewPromise\n * }\n * return $q.reject(rejection);\n * },\n *\n *\n *\n * // optional method\n * 'response': function(response) {\n * // do something on success\n * return response;\n * },\n *\n * // optional method\n * 'responseError': function(rejection) {\n * // do something on error\n * if (canRecover(rejection)) {\n * return responseOrNewPromise\n * }\n * return $q.reject(rejection);\n * }\n * };\n * });\n *\n * $httpProvider.interceptors.push('myHttpInterceptor');\n *\n *\n * // alternatively, register the interceptor via an anonymous factory\n * $httpProvider.interceptors.push(function($q, dependency1, dependency2) {\n * return {\n * 'request': function(config) {\n * // same as above\n * },\n *\n * 'response': function(response) {\n * // same as above\n * }\n * };\n * });\n * ```\n *\n * ## Security Considerations\n *\n * When designing web applications, consider security threats from:\n *\n * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)\n *\n * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n * pre-configured with strategies that address these issues, but for this to work backend server\n * cooperation is required.\n *\n * ### JSON Vulnerability Protection\n *\n * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n * allows third party website to turn your JSON resource URL into\n * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To\n * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n * Angular will automatically strip the prefix before processing it as JSON.\n *\n * For example if your server needs to return:\n * ```js\n * ['one','two']\n * ```\n *\n * which is vulnerable to attack, your server can return:\n * ```js\n * )]}',\n * ['one','two']\n * ```\n *\n * Angular will strip the prefix, before processing the JSON.\n *\n *\n * ### Cross Site Request Forgery (XSRF) Protection\n *\n * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which\n * an unauthorized site can gain your user's private data. Angular provides a mechanism\n * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only\n * JavaScript that runs on your domain could read the cookie, your server can be assured that\n * the XHR came from JavaScript running on your domain. The header will not be set for\n * cross-domain requests.\n *\n * To take advantage of this, your server needs to set a token in a JavaScript readable session\n * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the\n * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n * that only JavaScript running on your domain could have sent the request. The token must be\n * unique for each user and must be verifiable by the server (to prevent the JavaScript from\n * making up its own tokens). We recommend that the token is a digest of your site's\n * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography))\n * for added security.\n *\n * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName\n * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,\n * or the per-request config object.\n *\n *\n * @param {object} config Object describing the request to be made and how it should be\n * processed. The object has following properties:\n *\n * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n * - **params** – `{Object.}` – Map of strings or objects which will be turned\n * to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be\n * JSONified.\n * - **data** – `{string|Object}` – Data to be sent as the request message data.\n * - **headers** – `{Object}` – Map of strings or functions which return strings representing\n * HTTP headers to send to the server. If the return value of a function is null, the\n * header will not be sent.\n * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.\n * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.\n * - **transformRequest** –\n * `{function(data, headersGetter)|Array.}` –\n * transform function or an array of such functions. The transform function takes the http\n * request body and headers and returns its transformed (typically serialized) version.\n * See {@link ng.$http#overriding-the-default-transformations-per-request\n * Overriding the Default Transformations}\n * - **transformResponse** –\n * `{function(data, headersGetter, status)|Array.}` –\n * transform function or an array of such functions. The transform function takes the http\n * response body, headers and status and returns its transformed (typically deserialized) version.\n * See {@link ng.$http#overriding-the-default-transformations-per-request\n * Overriding the Default Transformations}\n * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n * GET request, otherwise if a cache instance built with\n * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n * caching.\n * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}\n * that should abort the request when resolved.\n * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the\n * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)\n * for more information.\n * - **responseType** - `{string}` - see\n * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).\n *\n * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n * standard `then` method and two http specific methods: `success` and `error`. The `then`\n * method takes two arguments a success and an error callback which will be called with a\n * response object. The `success` and `error` methods take a single argument - a function that\n * will be called when the request succeeds or fails respectively. The arguments passed into\n * these functions are destructured representation of the response object passed into the\n * `then` method. The response object has these properties:\n *\n * - **data** – `{string|Object}` – The response body transformed with the transform\n * functions.\n * - **status** – `{number}` – HTTP status code of the response.\n * - **headers** – `{function([headerName])}` – Header getter function.\n * - **config** – `{Object}` – The configuration object that was used to generate the request.\n * - **statusText** – `{string}` – HTTP status text of the response.\n *\n * @property {Array.} pendingRequests Array of config objects for currently pending\n * requests. This is primarily meant to be used for debugging purposes.\n *\n *\n * @example\n\n\n
\n \n \n
\n \n \n \n
http status code: {{status}}
\n
http response data: {{data}}
\n
\n
\n\n angular.module('httpExample', [])\n .controller('FetchController', ['$scope', '$http', '$templateCache',\n function($scope, $http, $templateCache) {\n $scope.method = 'GET';\n $scope.url = 'http-hello.html';\n\n $scope.fetch = function() {\n $scope.code = null;\n $scope.response = null;\n\n $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n success(function(data, status) {\n $scope.status = status;\n $scope.data = data;\n }).\n error(function(data, status) {\n $scope.data = data || \"Request failed\";\n $scope.status = status;\n });\n };\n\n $scope.updateModel = function(method, url) {\n $scope.method = method;\n $scope.url = url;\n };\n }]);\n\n\n Hello, $http!\n\n\n var status = element(by.binding('status'));\n var data = element(by.binding('data'));\n var fetchBtn = element(by.id('fetchbtn'));\n var sampleGetBtn = element(by.id('samplegetbtn'));\n var sampleJsonpBtn = element(by.id('samplejsonpbtn'));\n var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));\n\n it('should make an xhr GET request', function() {\n sampleGetBtn.click();\n fetchBtn.click();\n expect(status.getText()).toMatch('200');\n expect(data.getText()).toMatch(/Hello, \\$http!/);\n });\n\n// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185\n// it('should make a JSONP request to angularjs.org', function() {\n// sampleJsonpBtn.click();\n// fetchBtn.click();\n// expect(status.getText()).toMatch('200');\n// expect(data.getText()).toMatch(/Super Hero!/);\n// });\n\n it('should make JSONP request to invalid URL and invoke the error handler',\n function() {\n invalidJsonpBtn.click();\n fetchBtn.click();\n expect(status.getText()).toMatch('0');\n expect(data.getText()).toMatch('Request failed');\n });\n\n
\n */\n function $http(requestConfig) {\n\n if (!angular.isObject(requestConfig)) {\n throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig);\n }\n\n var config = extend({\n method: 'get',\n transformRequest: defaults.transformRequest,\n transformResponse: defaults.transformResponse\n }, requestConfig);\n\n config.headers = mergeHeaders(requestConfig);\n config.method = uppercase(config.method);\n\n var serverRequest = function(config) {\n var headers = config.headers;\n var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);\n\n // strip content-type if data is undefined\n if (isUndefined(reqData)) {\n forEach(headers, function(value, header) {\n if (lowercase(header) === 'content-type') {\n delete headers[header];\n }\n });\n }\n\n if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {\n config.withCredentials = defaults.withCredentials;\n }\n\n // send request\n return sendReq(config, reqData).then(transformResponse, transformResponse);\n };\n\n var chain = [serverRequest, undefined];\n var promise = $q.when(config);\n\n // apply interceptors\n forEach(reversedInterceptors, function(interceptor) {\n if (interceptor.request || interceptor.requestError) {\n chain.unshift(interceptor.request, interceptor.requestError);\n }\n if (interceptor.response || interceptor.responseError) {\n chain.push(interceptor.response, interceptor.responseError);\n }\n });\n\n while (chain.length) {\n var thenFn = chain.shift();\n var rejectFn = chain.shift();\n\n promise = promise.then(thenFn, rejectFn);\n }\n\n promise.success = function(fn) {\n promise.then(function(response) {\n fn(response.data, response.status, response.headers, config);\n });\n return promise;\n };\n\n promise.error = function(fn) {\n promise.then(null, function(response) {\n fn(response.data, response.status, response.headers, config);\n });\n return promise;\n };\n\n return promise;\n\n function transformResponse(response) {\n // make a copy since the response must be cacheable\n var resp = extend({}, response);\n if (!response.data) {\n resp.data = response.data;\n } else {\n resp.data = transformData(response.data, response.headers, response.status, config.transformResponse);\n }\n return (isSuccess(response.status))\n ? resp\n : $q.reject(resp);\n }\n\n function executeHeaderFns(headers) {\n var headerContent, processedHeaders = {};\n\n forEach(headers, function(headerFn, header) {\n if (isFunction(headerFn)) {\n headerContent = headerFn();\n if (headerContent != null) {\n processedHeaders[header] = headerContent;\n }\n } else {\n processedHeaders[header] = headerFn;\n }\n });\n\n return processedHeaders;\n }\n\n function mergeHeaders(config) {\n var defHeaders = defaults.headers,\n reqHeaders = extend({}, config.headers),\n defHeaderName, lowercaseDefHeaderName, reqHeaderName;\n\n defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);\n\n // using for-in instead of forEach to avoid unecessary iteration after header has been found\n defaultHeadersIteration:\n for (defHeaderName in defHeaders) {\n lowercaseDefHeaderName = lowercase(defHeaderName);\n\n for (reqHeaderName in reqHeaders) {\n if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {\n continue defaultHeadersIteration;\n }\n }\n\n reqHeaders[defHeaderName] = defHeaders[defHeaderName];\n }\n\n // execute if header value is a function for merged headers\n return executeHeaderFns(reqHeaders);\n }\n }\n\n $http.pendingRequests = [];\n\n /**\n * @ngdoc method\n * @name $http#get\n *\n * @description\n * Shortcut method to perform `GET` request.\n *\n * @param {string} url Relative or absolute URL specifying the destination of the request\n * @param {Object=} config Optional configuration object\n * @returns {HttpPromise} Future object\n */\n\n /**\n * @ngdoc method\n * @name $http#delete\n *\n * @description\n * Shortcut method to perform `DELETE` request.\n *\n * @param {string} url Relative or absolute URL specifying the destination of the request\n * @param {Object=} config Optional configuration object\n * @returns {HttpPromise} Future object\n */\n\n /**\n * @ngdoc method\n * @name $http#head\n *\n * @description\n * Shortcut method to perform `HEAD` request.\n *\n * @param {string} url Relative or absolute URL specifying the destination of the request\n * @param {Object=} config Optional configuration object\n * @returns {HttpPromise} Future object\n */\n\n /**\n * @ngdoc method\n * @name $http#jsonp\n *\n * @description\n * Shortcut method to perform `JSONP` request.\n *\n * @param {string} url Relative or absolute URL specifying the destination of the request.\n * The name of the callback should be the string `JSON_CALLBACK`.\n * @param {Object=} config Optional configuration object\n * @returns {HttpPromise} Future object\n */\n createShortMethods('get', 'delete', 'head', 'jsonp');\n\n /**\n * @ngdoc method\n * @name $http#post\n *\n * @description\n * Shortcut method to perform `POST` request.\n *\n * @param {string} url Relative or absolute URL specifying the destination of the request\n * @param {*} data Request content\n * @param {Object=} config Optional configuration object\n * @returns {HttpPromise} Future object\n */\n\n /**\n * @ngdoc method\n * @name $http#put\n *\n * @description\n * Shortcut method to perform `PUT` request.\n *\n * @param {string} url Relative or absolute URL specifying the destination of the request\n * @param {*} data Request content\n * @param {Object=} config Optional configuration object\n * @returns {HttpPromise} Future object\n */\n\n /**\n * @ngdoc method\n * @name $http#patch\n *\n * @description\n * Shortcut method to perform `PATCH` request.\n *\n * @param {string} url Relative or absolute URL specifying the destination of the request\n * @param {*} data Request content\n * @param {Object=} config Optional configuration object\n * @returns {HttpPromise} Future object\n */\n createShortMethodsWithData('post', 'put', 'patch');\n\n /**\n * @ngdoc property\n * @name $http#defaults\n *\n * @description\n * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n * default headers, withCredentials as well as request and response transformations.\n *\n * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n */\n $http.defaults = defaults;\n\n\n return $http;\n\n\n function createShortMethods(names) {\n forEach(arguments, function(name) {\n $http[name] = function(url, config) {\n return $http(extend(config || {}, {\n method: name,\n url: url\n }));\n };\n });\n }\n\n\n function createShortMethodsWithData(name) {\n forEach(arguments, function(name) {\n $http[name] = function(url, data, config) {\n return $http(extend(config || {}, {\n method: name,\n url: url,\n data: data\n }));\n };\n });\n }\n\n\n /**\n * Makes the request.\n *\n * !!! ACCESSES CLOSURE VARS:\n * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests\n */\n function sendReq(config, reqData) {\n var deferred = $q.defer(),\n promise = deferred.promise,\n cache,\n cachedResp,\n reqHeaders = config.headers,\n url = buildUrl(config.url, config.params);\n\n $http.pendingRequests.push(config);\n promise.then(removePendingReq, removePendingReq);\n\n\n if ((config.cache || defaults.cache) && config.cache !== false &&\n (config.method === 'GET' || config.method === 'JSONP')) {\n cache = isObject(config.cache) ? config.cache\n : isObject(defaults.cache) ? defaults.cache\n : defaultCache;\n }\n\n if (cache) {\n cachedResp = cache.get(url);\n if (isDefined(cachedResp)) {\n if (isPromiseLike(cachedResp)) {\n // cached request has already been sent, but there is no response yet\n cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);\n } else {\n // serving from cache\n if (isArray(cachedResp)) {\n resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);\n } else {\n resolvePromise(cachedResp, 200, {}, 'OK');\n }\n }\n } else {\n // put the promise for the non-transformed response into cache as a placeholder\n cache.put(url, promise);\n }\n }\n\n\n // if we won't have the response in cache, set the xsrf headers and\n // send the request to the backend\n if (isUndefined(cachedResp)) {\n var xsrfValue = urlIsSameOrigin(config.url)\n ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]\n : undefined;\n if (xsrfValue) {\n reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;\n }\n\n $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n config.withCredentials, config.responseType);\n }\n\n return promise;\n\n\n /**\n * Callback registered to $httpBackend():\n * - caches the response if desired\n * - resolves the raw $http promise\n * - calls $apply\n */\n function done(status, response, headersString, statusText) {\n if (cache) {\n if (isSuccess(status)) {\n cache.put(url, [status, response, parseHeaders(headersString), statusText]);\n } else {\n // remove promise from the cache\n cache.remove(url);\n }\n }\n\n function resolveHttpPromise() {\n resolvePromise(response, status, headersString, statusText);\n }\n\n if (useApplyAsync) {\n $rootScope.$applyAsync(resolveHttpPromise);\n } else {\n resolveHttpPromise();\n if (!$rootScope.$$phase) $rootScope.$apply();\n }\n }\n\n\n /**\n * Resolves the raw $http promise.\n */\n function resolvePromise(response, status, headers, statusText) {\n // normalize internal statuses to 0\n status = Math.max(status, 0);\n\n (isSuccess(status) ? deferred.resolve : deferred.reject)({\n data: response,\n status: status,\n headers: headersGetter(headers),\n config: config,\n statusText: statusText\n });\n }\n\n function resolvePromiseWithResult(result) {\n resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);\n }\n\n function removePendingReq() {\n var idx = $http.pendingRequests.indexOf(config);\n if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n }\n }\n\n\n function buildUrl(url, params) {\n if (!params) return url;\n var parts = [];\n forEachSorted(params, function(value, key) {\n if (value === null || isUndefined(value)) return;\n if (!isArray(value)) value = [value];\n\n forEach(value, function(v) {\n if (isObject(v)) {\n if (isDate(v)) {\n v = v.toISOString();\n } else {\n v = toJson(v);\n }\n }\n parts.push(encodeUriQuery(key) + '=' +\n encodeUriQuery(v));\n });\n });\n if (parts.length > 0) {\n url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n }\n return url;\n }\n }];\n}\n\nfunction createXhr() {\n return new window.XMLHttpRequest();\n}\n\n/**\n * @ngdoc service\n * @name $httpBackend\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]);\n }];\n}\n\nfunction createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {\n // TODO(vojta): fix the signature\n return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {\n $browser.$$incOutstandingRequestCount();\n url = url || $browser.url();\n\n if (lowercase(method) == 'jsonp') {\n var callbackId = '_' + (callbacks.counter++).toString(36);\n callbacks[callbackId] = function(data) {\n callbacks[callbackId].data = data;\n callbacks[callbackId].called = true;\n };\n\n var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n callbackId, function(status, text) {\n completeRequest(callback, status, callbacks[callbackId].data, \"\", text);\n callbacks[callbackId] = noop;\n });\n } else {\n\n var xhr = createXhr();\n\n xhr.open(method, url, true);\n forEach(headers, function(value, key) {\n if (isDefined(value)) {\n xhr.setRequestHeader(key, value);\n }\n });\n\n xhr.onload = function requestLoaded() {\n var statusText = xhr.statusText || '';\n\n // responseText is the old-school way of retrieving response (supported by IE8 & 9)\n // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)\n var response = ('response' in xhr) ? xhr.response : xhr.responseText;\n\n // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)\n var status = xhr.status === 1223 ? 204 : xhr.status;\n\n // fix status code when it is 0 (0 status is undocumented).\n // Occurs when accessing file resources or on Android 4.1 stock browser\n // while retrieving files from application cache.\n if (status === 0) {\n status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;\n }\n\n completeRequest(callback,\n status,\n response,\n xhr.getAllResponseHeaders(),\n statusText);\n };\n\n var requestError = function() {\n // The response is always empty\n // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error\n completeRequest(callback, -1, null, null, '');\n };\n\n xhr.onerror = requestError;\n xhr.onabort = requestError;\n\n if (withCredentials) {\n xhr.withCredentials = true;\n }\n\n if (responseType) {\n try {\n xhr.responseType = responseType;\n } catch (e) {\n // WebKit added support for the json responseType value on 09/03/2013\n // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are\n // known to throw when setting the value \"json\" as the response type. Other older\n // browsers implementing the responseType\n //\n // The json response type can be ignored if not supported, because JSON payloads are\n // parsed on the client-side regardless.\n if (responseType !== 'json') {\n throw e;\n }\n }\n }\n\n xhr.send(post || null);\n }\n\n if (timeout > 0) {\n var timeoutId = $browserDefer(timeoutRequest, timeout);\n } else if (isPromiseLike(timeout)) {\n timeout.then(timeoutRequest);\n }\n\n\n function timeoutRequest() {\n jsonpDone && jsonpDone();\n xhr && xhr.abort();\n }\n\n function completeRequest(callback, status, response, headersString, statusText) {\n // cancel timeout and subsequent timeout promise resolution\n if (timeoutId !== undefined) {\n $browserDefer.cancel(timeoutId);\n }\n jsonpDone = xhr = null;\n\n callback(status, response, headersString, statusText);\n $browser.$$completeOutstandingRequest(noop);\n }\n };\n\n function jsonpReq(url, callbackId, done) {\n // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n // - fetches local scripts via XHR and evals them\n // - adds and immediately removes script elements from the document\n var script = rawDocument.createElement('script'), callback = null;\n script.type = \"text/javascript\";\n script.src = url;\n script.async = true;\n\n callback = function(event) {\n removeEventListenerFn(script, \"load\", callback);\n removeEventListenerFn(script, \"error\", callback);\n rawDocument.body.removeChild(script);\n script = null;\n var status = -1;\n var text = \"unknown\";\n\n if (event) {\n if (event.type === \"load\" && !callbacks[callbackId].called) {\n event = { type: \"error\" };\n }\n text = event.type;\n status = event.type === \"error\" ? 404 : 200;\n }\n\n if (done) {\n done(status, text);\n }\n };\n\n addEventListenerFn(script, \"load\", callback);\n addEventListenerFn(script, \"error\", callback);\n rawDocument.body.appendChild(script);\n return callback;\n }\n}\n\nvar $interpolateMinErr = minErr('$interpolate');\n\n/**\n * @ngdoc provider\n * @name $interpolateProvider\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n *\n * @example\n\n\n\n
\n //demo.label//\n
\n
\n\n it('should interpolate binding with custom symbols', function() {\n expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');\n });\n\n
\n */\nfunction $InterpolateProvider() {\n var startSymbol = '{{';\n var endSymbol = '}}';\n\n /**\n * @ngdoc method\n * @name $interpolateProvider#startSymbol\n * @description\n * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n *\n * @param {string=} value new value to set the starting symbol to.\n * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n */\n this.startSymbol = function(value) {\n if (value) {\n startSymbol = value;\n return this;\n } else {\n return startSymbol;\n }\n };\n\n /**\n * @ngdoc method\n * @name $interpolateProvider#endSymbol\n * @description\n * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n *\n * @param {string=} value new value to set the ending symbol to.\n * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n */\n this.endSymbol = function(value) {\n if (value) {\n endSymbol = value;\n return this;\n } else {\n return endSymbol;\n }\n };\n\n\n this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {\n var startSymbolLength = startSymbol.length,\n endSymbolLength = endSymbol.length,\n escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'),\n escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g');\n\n function escape(ch) {\n return '\\\\\\\\\\\\' + ch;\n }\n\n /**\n * @ngdoc service\n * @name $interpolate\n * @kind function\n *\n * @requires $parse\n * @requires $sce\n *\n * @description\n *\n * Compiles a string with markup into an interpolation function. This service is used by the\n * HTML {@link ng.$compile $compile} service for data binding. See\n * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n * interpolation markup.\n *\n *\n * ```js\n * var $interpolate = ...; // injected\n * var exp = $interpolate('Hello {{name | uppercase}}!');\n * expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');\n * ```\n *\n * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is\n * `true`, the interpolation function will return `undefined` unless all embedded expressions\n * evaluate to a value other than `undefined`.\n *\n * ```js\n * var $interpolate = ...; // injected\n * var context = {greeting: 'Hello', name: undefined };\n *\n * // default \"forgiving\" mode\n * var exp = $interpolate('{{greeting}} {{name}}!');\n * expect(exp(context)).toEqual('Hello !');\n *\n * // \"allOrNothing\" mode\n * exp = $interpolate('{{greeting}} {{name}}!', false, null, true);\n * expect(exp(context)).toBeUndefined();\n * context.name = 'Angular';\n * expect(exp(context)).toEqual('Hello Angular!');\n * ```\n *\n * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior.\n *\n * ####Escaped Interpolation\n * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers\n * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash).\n * It will be rendered as a regular start/end marker, and will not be interpreted as an expression\n * or binding.\n *\n * This enables web-servers to prevent script injection attacks and defacing attacks, to some\n * degree, while also enabling code examples to work without relying on the\n * {@link ng.directive:ngNonBindable ngNonBindable} directive.\n *\n * **For security purposes, it is strongly encouraged that web servers escape user-supplied data,\n * replacing angle brackets (<, >) with &lt; and &gt; respectively, and replacing all\n * interpolation start/end markers with their escaped counterparts.**\n *\n * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered\n * output when the $interpolate service processes the text. So, for HTML elements interpolated\n * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter\n * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such,\n * this is typically useful only when user-data is used in rendering a template from the server, or\n * when otherwise untrusted data is used by a directive.\n *\n * \n * \n *
\n *

{{apptitle}}: \\{\\{ username = \"defaced value\"; \\}\\}\n *

\n *

{{username}} attempts to inject code which will deface the\n * application, but fails to accomplish their task, because the server has correctly\n * escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash)\n * characters.

\n *

Instead, the result of the attempted script injection is visible, and can be removed\n * from the database by an administrator.

\n *
\n *
\n *
\n *\n * @param {string} text The text with markup to interpolate.\n * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n * embedded expression in order to return an interpolation function. Strings with no\n * embedded expression will return null for the interpolation function.\n * @param {string=} trustedContext when provided, the returned function passes the interpolated\n * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,\n * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that\n * provides Strict Contextual Escaping for details.\n * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined\n * unless all embedded expressions evaluate to a value other than `undefined`.\n * @returns {function(context)} an interpolation function which is used to compute the\n * interpolated string. The function has these parameters:\n *\n * - `context`: evaluation context for all expressions embedded in the interpolated text\n */\n function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {\n allOrNothing = !!allOrNothing;\n var startIndex,\n endIndex,\n index = 0,\n expressions = [],\n parseFns = [],\n textLength = text.length,\n exp,\n concat = [],\n expressionPositions = [];\n\n while (index < textLength) {\n if (((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) {\n if (index !== startIndex) {\n concat.push(unescapeText(text.substring(index, startIndex)));\n }\n exp = text.substring(startIndex + startSymbolLength, endIndex);\n expressions.push(exp);\n parseFns.push($parse(exp, parseStringifyInterceptor));\n index = endIndex + endSymbolLength;\n expressionPositions.push(concat.length);\n concat.push('');\n } else {\n // we did not find an interpolation, so we have to add the remainder to the separators array\n if (index !== textLength) {\n concat.push(unescapeText(text.substring(index)));\n }\n break;\n }\n }\n\n // Concatenating expressions makes it hard to reason about whether some combination of\n // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a\n // single expression be used for iframe[src], object[src], etc., we ensure that the value\n // that's used is assigned or constructed by some JS code somewhere that is more testable or\n // make it obvious that you bound the value to some user controlled value. This helps reduce\n // the load when auditing for XSS issues.\n if (trustedContext && concat.length > 1) {\n throw $interpolateMinErr('noconcat',\n \"Error while interpolating: {0}\\nStrict Contextual Escaping disallows \" +\n \"interpolations that concatenate multiple expressions when a trusted value is \" +\n \"required. See http://docs.angularjs.org/api/ng.$sce\", text);\n }\n\n if (!mustHaveExpression || expressions.length) {\n var compute = function(values) {\n for (var i = 0, ii = expressions.length; i < ii; i++) {\n if (allOrNothing && isUndefined(values[i])) return;\n concat[expressionPositions[i]] = values[i];\n }\n return concat.join('');\n };\n\n var getValue = function(value) {\n return trustedContext ?\n $sce.getTrusted(trustedContext, value) :\n $sce.valueOf(value);\n };\n\n var stringify = function(value) {\n if (value == null) { // null || undefined\n return '';\n }\n switch (typeof value) {\n case 'string':\n break;\n case 'number':\n value = '' + value;\n break;\n default:\n value = toJson(value);\n }\n\n return value;\n };\n\n return extend(function interpolationFn(context) {\n var i = 0;\n var ii = expressions.length;\n var values = new Array(ii);\n\n try {\n for (; i < ii; i++) {\n values[i] = parseFns[i](context);\n }\n\n return compute(values);\n } catch (err) {\n var newErr = $interpolateMinErr('interr', \"Can't interpolate: {0}\\n{1}\", text,\n err.toString());\n $exceptionHandler(newErr);\n }\n\n }, {\n // all of these properties are undocumented for now\n exp: text, //just for compatibility with regular watchers created via $watch\n expressions: expressions,\n $$watchDelegate: function(scope, listener, objectEquality) {\n var lastValue;\n return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {\n var currValue = compute(values);\n if (isFunction(listener)) {\n listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);\n }\n lastValue = currValue;\n }, objectEquality);\n }\n });\n }\n\n function unescapeText(text) {\n return text.replace(escapedStartRegexp, startSymbol).\n replace(escapedEndRegexp, endSymbol);\n }\n\n function parseStringifyInterceptor(value) {\n try {\n value = getValue(value);\n return allOrNothing && !isDefined(value) ? value : stringify(value);\n } catch (err) {\n var newErr = $interpolateMinErr('interr', \"Can't interpolate: {0}\\n{1}\", text,\n err.toString());\n $exceptionHandler(newErr);\n }\n }\n }\n\n\n /**\n * @ngdoc method\n * @name $interpolate#startSymbol\n * @description\n * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n *\n * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change\n * the symbol.\n *\n * @returns {string} start symbol.\n */\n $interpolate.startSymbol = function() {\n return startSymbol;\n };\n\n\n /**\n * @ngdoc method\n * @name $interpolate#endSymbol\n * @description\n * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n *\n * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change\n * the symbol.\n *\n * @returns {string} end symbol.\n */\n $interpolate.endSymbol = function() {\n return endSymbol;\n };\n\n return $interpolate;\n }];\n}\n\nfunction $IntervalProvider() {\n this.$get = ['$rootScope', '$window', '$q', '$$q',\n function($rootScope, $window, $q, $$q) {\n var intervals = {};\n\n\n /**\n * @ngdoc service\n * @name $interval\n *\n * @description\n * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`\n * milliseconds.\n *\n * The return value of registering an interval function is a promise. This promise will be\n * notified upon each tick of the interval, and will be resolved after `count` iterations, or\n * run indefinitely if `count` is not defined. The value of the notification will be the\n * number of iterations that have run.\n * To cancel an interval, call `$interval.cancel(promise)`.\n *\n * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to\n * move forward by `millis` milliseconds and trigger any functions scheduled to run in that\n * time.\n *\n *
\n * **Note**: Intervals created by this service must be explicitly destroyed when you are finished\n * with them. In particular they are not automatically destroyed when a controller's scope or a\n * directive's element are destroyed.\n * You should take this into consideration and make sure to always cancel the interval at the\n * appropriate moment. See the example below for more details on how and when to do this.\n *
\n *\n * @param {function()} fn A function that should be called repeatedly.\n * @param {number} delay Number of milliseconds between each function call.\n * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat\n * indefinitely.\n * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise\n * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n * @returns {promise} A promise which will be notified on each iteration.\n *\n * @example\n * \n * \n * \n *\n *
\n *
\n * Date format:
\n * Current time is: \n *
\n * Blood 1 : {{blood_1}}\n * Blood 2 : {{blood_2}}\n * \n * \n * \n *
\n *
\n *\n *
\n *
\n */\n function interval(fn, delay, count, invokeApply) {\n var setInterval = $window.setInterval,\n clearInterval = $window.clearInterval,\n iteration = 0,\n skipApply = (isDefined(invokeApply) && !invokeApply),\n deferred = (skipApply ? $$q : $q).defer(),\n promise = deferred.promise;\n\n count = isDefined(count) ? count : 0;\n\n promise.then(null, null, fn);\n\n promise.$$intervalId = setInterval(function tick() {\n deferred.notify(iteration++);\n\n if (count > 0 && iteration >= count) {\n deferred.resolve(iteration);\n clearInterval(promise.$$intervalId);\n delete intervals[promise.$$intervalId];\n }\n\n if (!skipApply) $rootScope.$apply();\n\n }, delay);\n\n intervals[promise.$$intervalId] = deferred;\n\n return promise;\n }\n\n\n /**\n * @ngdoc method\n * @name $interval#cancel\n *\n * @description\n * Cancels a task associated with the `promise`.\n *\n * @param {promise} promise returned by the `$interval` function.\n * @returns {boolean} Returns `true` if the task was successfully canceled.\n */\n interval.cancel = function(promise) {\n if (promise && promise.$$intervalId in intervals) {\n intervals[promise.$$intervalId].reject('canceled');\n $window.clearInterval(promise.$$intervalId);\n delete intervals[promise.$$intervalId];\n return true;\n }\n return false;\n };\n\n return interval;\n }];\n}\n\n/**\n * @ngdoc service\n * @name $locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider() {\n this.$get = function() {\n return {\n id: 'en-us',\n\n NUMBER_FORMATS: {\n DECIMAL_SEP: '.',\n GROUP_SEP: ',',\n PATTERNS: [\n { // Decimal Pattern\n minInt: 1,\n minFrac: 0,\n maxFrac: 3,\n posPre: '',\n posSuf: '',\n negPre: '-',\n negSuf: '',\n gSize: 3,\n lgSize: 3\n },{ //Currency Pattern\n minInt: 1,\n minFrac: 2,\n maxFrac: 2,\n posPre: '\\u00A4',\n posSuf: '',\n negPre: '(\\u00A4',\n negSuf: ')',\n gSize: 3,\n lgSize: 3\n }\n ],\n CURRENCY_SYM: '$'\n },\n\n DATETIME_FORMATS: {\n MONTH:\n 'January,February,March,April,May,June,July,August,September,October,November,December'\n .split(','),\n SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n AMPMS: ['AM','PM'],\n medium: 'MMM d, y h:mm:ss a',\n 'short': 'M/d/yy h:mm a',\n fullDate: 'EEEE, MMMM d, y',\n longDate: 'MMMM d, y',\n mediumDate: 'MMM d, y',\n shortDate: 'M/d/yy',\n mediumTime: 'h:mm:ss a',\n shortTime: 'h:mm a'\n },\n\n pluralCat: function(num) {\n if (num === 1) {\n return 'one';\n }\n return 'other';\n }\n };\n };\n}\n\nvar PATH_MATCH = /^([^\\?#]*)(\\?([^#]*))?(#(.*))?$/,\n DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\nvar $locationMinErr = minErr('$location');\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n var segments = path.split('/'),\n i = segments.length;\n\n while (i--) {\n segments[i] = encodeUriSegment(segments[i]);\n }\n\n return segments.join('/');\n}\n\nfunction parseAbsoluteUrl(absoluteUrl, locationObj) {\n var parsedUrl = urlResolve(absoluteUrl);\n\n locationObj.$$protocol = parsedUrl.protocol;\n locationObj.$$host = parsedUrl.hostname;\n locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;\n}\n\n\nfunction parseAppUrl(relativeUrl, locationObj) {\n var prefixed = (relativeUrl.charAt(0) !== '/');\n if (prefixed) {\n relativeUrl = '/' + relativeUrl;\n }\n var match = urlResolve(relativeUrl);\n locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?\n match.pathname.substring(1) : match.pathname);\n locationObj.$$search = parseKeyValue(match.search);\n locationObj.$$hash = decodeURIComponent(match.hash);\n\n // make sure path starts with '/';\n if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {\n locationObj.$$path = '/' + locationObj.$$path;\n }\n}\n\n\n/**\n *\n * @param {string} begin\n * @param {string} whole\n * @returns {string} returns text from whole after begin or undefined if it does not begin with\n * expected string.\n */\nfunction beginsWith(begin, whole) {\n if (whole.indexOf(begin) === 0) {\n return whole.substr(begin.length);\n }\n}\n\n\nfunction stripHash(url) {\n var index = url.indexOf('#');\n return index == -1 ? url : url.substr(0, index);\n}\n\nfunction trimEmptyHash(url) {\n return url.replace(/(#.+)|#$/, '$1');\n}\n\n\nfunction stripFile(url) {\n return url.substr(0, stripHash(url).lastIndexOf('/') + 1);\n}\n\n/* return the server only (scheme://host:port) */\nfunction serverBase(url) {\n return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));\n}\n\n\n/**\n * LocationHtml5Url represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} basePrefix url path prefix\n */\nfunction LocationHtml5Url(appBase, basePrefix) {\n this.$$html5 = true;\n basePrefix = basePrefix || '';\n var appBaseNoFile = stripFile(appBase);\n parseAbsoluteUrl(appBase, this);\n\n\n /**\n * Parse given html5 (regular) url string into properties\n * @param {string} url HTML5 url\n * @private\n */\n this.$$parse = function(url) {\n var pathUrl = beginsWith(appBaseNoFile, url);\n if (!isString(pathUrl)) {\n throw $locationMinErr('ipthprfx', 'Invalid url \"{0}\", missing path prefix \"{1}\".', url,\n appBaseNoFile);\n }\n\n parseAppUrl(pathUrl, this);\n\n if (!this.$$path) {\n this.$$path = '/';\n }\n\n this.$$compose();\n };\n\n /**\n * Compose url and update `absUrl` property\n * @private\n */\n this.$$compose = function() {\n var search = toKeyValue(this.$$search),\n hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'\n };\n\n this.$$parseLinkUrl = function(url, relHref) {\n if (relHref && relHref[0] === '#') {\n // special case for links to hash fragments:\n // keep the old url and only replace the hash fragment\n this.hash(relHref.slice(1));\n return true;\n }\n var appUrl, prevAppUrl;\n var rewrittenUrl;\n\n if ((appUrl = beginsWith(appBase, url)) !== undefined) {\n prevAppUrl = appUrl;\n if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) {\n rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);\n } else {\n rewrittenUrl = appBase + prevAppUrl;\n }\n } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) {\n rewrittenUrl = appBaseNoFile + appUrl;\n } else if (appBaseNoFile == url + '/') {\n rewrittenUrl = appBaseNoFile;\n }\n if (rewrittenUrl) {\n this.$$parse(rewrittenUrl);\n }\n return !!rewrittenUrl;\n };\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when developer doesn't opt into html5 mode.\n * It also serves as the base class for html5 mode fallback on legacy browsers.\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} hashPrefix hashbang prefix\n */\nfunction LocationHashbangUrl(appBase, hashPrefix) {\n var appBaseNoFile = stripFile(appBase);\n\n parseAbsoluteUrl(appBase, this);\n\n\n /**\n * Parse given hashbang url into properties\n * @param {string} url Hashbang url\n * @private\n */\n this.$$parse = function(url) {\n var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);\n var withoutHashUrl;\n\n if (withoutBaseUrl.charAt(0) === '#') {\n\n // The rest of the url starts with a hash so we have\n // got either a hashbang path or a plain hash fragment\n withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);\n if (isUndefined(withoutHashUrl)) {\n // There was no hashbang prefix so we just have a hash fragment\n withoutHashUrl = withoutBaseUrl;\n }\n\n } else {\n // There was no hashbang path nor hash fragment:\n // If we are in HTML5 mode we use what is left as the path;\n // Otherwise we ignore what is left\n withoutHashUrl = this.$$html5 ? withoutBaseUrl : '';\n }\n\n parseAppUrl(withoutHashUrl, this);\n\n this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);\n\n this.$$compose();\n\n /*\n * In Windows, on an anchor node on documents loaded from\n * the filesystem, the browser will return a pathname\n * prefixed with the drive name ('/C:/path') when a\n * pathname without a drive is set:\n * * a.setAttribute('href', '/foo')\n * * a.pathname === '/C:/foo' //true\n *\n * Inside of Angular, we're always using pathnames that\n * do not include drive names for routing.\n */\n function removeWindowsDriveName(path, url, base) {\n /*\n Matches paths for file protocol on windows,\n such as /C:/foo/bar, and captures only /foo/bar.\n */\n var windowsFilePathExp = /^\\/[A-Z]:(\\/.*)/;\n\n var firstPathSegmentMatch;\n\n //Get the relative path from the input URL.\n if (url.indexOf(base) === 0) {\n url = url.replace(base, '');\n }\n\n // The input URL intentionally contains a first path segment that ends with a colon.\n if (windowsFilePathExp.exec(url)) {\n return path;\n }\n\n firstPathSegmentMatch = windowsFilePathExp.exec(path);\n return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;\n }\n };\n\n /**\n * Compose hashbang url and update `absUrl` property\n * @private\n */\n this.$$compose = function() {\n var search = toKeyValue(this.$$search),\n hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');\n };\n\n this.$$parseLinkUrl = function(url, relHref) {\n if (stripHash(appBase) == stripHash(url)) {\n this.$$parse(url);\n return true;\n }\n return false;\n };\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is enabled but the browser\n * does not support it.\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} hashPrefix hashbang prefix\n */\nfunction LocationHashbangInHtml5Url(appBase, hashPrefix) {\n this.$$html5 = true;\n LocationHashbangUrl.apply(this, arguments);\n\n var appBaseNoFile = stripFile(appBase);\n\n this.$$parseLinkUrl = function(url, relHref) {\n if (relHref && relHref[0] === '#') {\n // special case for links to hash fragments:\n // keep the old url and only replace the hash fragment\n this.hash(relHref.slice(1));\n return true;\n }\n\n var rewrittenUrl;\n var appUrl;\n\n if (appBase == stripHash(url)) {\n rewrittenUrl = url;\n } else if ((appUrl = beginsWith(appBaseNoFile, url))) {\n rewrittenUrl = appBase + hashPrefix + appUrl;\n } else if (appBaseNoFile === url + '/') {\n rewrittenUrl = appBaseNoFile;\n }\n if (rewrittenUrl) {\n this.$$parse(rewrittenUrl);\n }\n return !!rewrittenUrl;\n };\n\n this.$$compose = function() {\n var search = toKeyValue(this.$$search),\n hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#'\n this.$$absUrl = appBase + hashPrefix + this.$$url;\n };\n\n}\n\n\nvar locationPrototype = {\n\n /**\n * Are we in html5 mode?\n * @private\n */\n $$html5: false,\n\n /**\n * Has any change been replacing?\n * @private\n */\n $$replace: false,\n\n /**\n * @ngdoc method\n * @name $location#absUrl\n *\n * @description\n * This method is getter only.\n *\n * Return full url representation with all segments encoded according to rules specified in\n * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).\n *\n *\n * ```js\n * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n * var absUrl = $location.absUrl();\n * // => \"http://example.com/#/some/path?foo=bar&baz=xoxo\"\n * ```\n *\n * @return {string} full url\n */\n absUrl: locationGetter('$$absUrl'),\n\n /**\n * @ngdoc method\n * @name $location#url\n *\n * @description\n * This method is getter / setter.\n *\n * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n *\n * Change path, search and hash, when called with parameter and return `$location`.\n *\n *\n * ```js\n * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n * var url = $location.url();\n * // => \"/some/path?foo=bar&baz=xoxo\"\n * ```\n *\n * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n * @return {string} url\n */\n url: function(url) {\n if (isUndefined(url))\n return this.$$url;\n\n var match = PATH_MATCH.exec(url);\n if (match[1] || url === '') this.path(decodeURIComponent(match[1]));\n if (match[2] || match[1] || url === '') this.search(match[3] || '');\n this.hash(match[5] || '');\n\n return this;\n },\n\n /**\n * @ngdoc method\n * @name $location#protocol\n *\n * @description\n * This method is getter only.\n *\n * Return protocol of current url.\n *\n *\n * ```js\n * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n * var protocol = $location.protocol();\n * // => \"http\"\n * ```\n *\n * @return {string} protocol of current url\n */\n protocol: locationGetter('$$protocol'),\n\n /**\n * @ngdoc method\n * @name $location#host\n *\n * @description\n * This method is getter only.\n *\n * Return host of current url.\n *\n *\n * ```js\n * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n * var host = $location.host();\n * // => \"example.com\"\n * ```\n *\n * @return {string} host of current url.\n */\n host: locationGetter('$$host'),\n\n /**\n * @ngdoc method\n * @name $location#port\n *\n * @description\n * This method is getter only.\n *\n * Return port of current url.\n *\n *\n * ```js\n * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n * var port = $location.port();\n * // => 80\n * ```\n *\n * @return {Number} port\n */\n port: locationGetter('$$port'),\n\n /**\n * @ngdoc method\n * @name $location#path\n *\n * @description\n * This method is getter / setter.\n *\n * Return path of current url when called without any parameter.\n *\n * Change path when called with parameter and return `$location`.\n *\n * Note: Path should always begin with forward slash (/), this method will add the forward slash\n * if it is missing.\n *\n *\n * ```js\n * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n * var path = $location.path();\n * // => \"/some/path\"\n * ```\n *\n * @param {(string|number)=} path New path\n * @return {string} path\n */\n path: locationGetterSetter('$$path', function(path) {\n path = path !== null ? path.toString() : '';\n return path.charAt(0) == '/' ? path : '/' + path;\n }),\n\n /**\n * @ngdoc method\n * @name $location#search\n *\n * @description\n * This method is getter / setter.\n *\n * Return search part (as object) of current url when called without any parameter.\n *\n * Change search part when called with parameter and return `$location`.\n *\n *\n * ```js\n * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n * var searchObject = $location.search();\n * // => {foo: 'bar', baz: 'xoxo'}\n *\n * // set foo to 'yipee'\n * $location.search('foo', 'yipee');\n * // $location.search() => {foo: 'yipee', baz: 'xoxo'}\n * ```\n *\n * @param {string|Object.|Object.>} search New search params - string or\n * hash object.\n *\n * When called with a single argument the method acts as a setter, setting the `search` component\n * of `$location` to the specified value.\n *\n * If the argument is a hash object containing an array of values, these values will be encoded\n * as duplicate search parameters in the url.\n *\n * @param {(string|Number|Array|boolean)=} paramValue If `search` is a string or number, then `paramValue`\n * will override only a single search property.\n *\n * If `paramValue` is an array, it will override the property of the `search` component of\n * `$location` specified via the first argument.\n *\n * If `paramValue` is `null`, the property specified via the first argument will be deleted.\n *\n * If `paramValue` is `true`, the property specified via the first argument will be added with no\n * value nor trailing equal sign.\n *\n * @return {Object} If called with no arguments returns the parsed `search` object. If called with\n * one or more arguments returns `$location` object itself.\n */\n search: function(search, paramValue) {\n switch (arguments.length) {\n case 0:\n return this.$$search;\n case 1:\n if (isString(search) || isNumber(search)) {\n search = search.toString();\n this.$$search = parseKeyValue(search);\n } else if (isObject(search)) {\n search = copy(search, {});\n // remove object undefined or null properties\n forEach(search, function(value, key) {\n if (value == null) delete search[key];\n });\n\n this.$$search = search;\n } else {\n throw $locationMinErr('isrcharg',\n 'The first argument of the `$location#search()` call must be a string or an object.');\n }\n break;\n default:\n if (isUndefined(paramValue) || paramValue === null) {\n delete this.$$search[search];\n } else {\n this.$$search[search] = paramValue;\n }\n }\n\n this.$$compose();\n return this;\n },\n\n /**\n * @ngdoc method\n * @name $location#hash\n *\n * @description\n * This method is getter / setter.\n *\n * Return hash fragment when called without any parameter.\n *\n * Change hash fragment when called with parameter and return `$location`.\n *\n *\n * ```js\n * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue\n * var hash = $location.hash();\n * // => \"hashValue\"\n * ```\n *\n * @param {(string|number)=} hash New hash fragment\n * @return {string} hash\n */\n hash: locationGetterSetter('$$hash', function(hash) {\n return hash !== null ? hash.toString() : '';\n }),\n\n /**\n * @ngdoc method\n * @name $location#replace\n *\n * @description\n * If called, all changes to $location during current `$digest` will be replacing current history\n * record, instead of adding new one.\n */\n replace: function() {\n this.$$replace = true;\n return this;\n }\n};\n\nforEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) {\n Location.prototype = Object.create(locationPrototype);\n\n /**\n * @ngdoc method\n * @name $location#state\n *\n * @description\n * This method is getter / setter.\n *\n * Return the history state object when called without any parameter.\n *\n * Change the history state object when called with one parameter and return `$location`.\n * The state object is later passed to `pushState` or `replaceState`.\n *\n * NOTE: This method is supported only in HTML5 mode and only in browsers supporting\n * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support\n * older browsers (like IE9 or Android < 4.0), don't use this method.\n *\n * @param {object=} state State object for pushState or replaceState\n * @return {object} state\n */\n Location.prototype.state = function(state) {\n if (!arguments.length)\n return this.$$state;\n\n if (Location !== LocationHtml5Url || !this.$$html5) {\n throw $locationMinErr('nostate', 'History API state support is available only ' +\n 'in HTML5 mode and only in browsers supporting HTML5 History API');\n }\n // The user might modify `stateObject` after invoking `$location.state(stateObject)`\n // but we're changing the $$state reference to $browser.state() during the $digest\n // so the modification window is narrow.\n this.$$state = isUndefined(state) ? null : state;\n\n return this;\n };\n});\n\n\nfunction locationGetter(property) {\n return function() {\n return this[property];\n };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n return function(value) {\n if (isUndefined(value))\n return this[property];\n\n this[property] = preprocess(value);\n this.$$compose();\n\n return this;\n };\n}\n\n\n/**\n * @ngdoc service\n * @name $location\n *\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n * - Watch and observe the URL.\n * - Change the URL.\n * - Synchronizes the URL with the browser when the user\n * - Changes the address bar.\n * - Clicks the back or forward button (or clicks a History link).\n * - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/$location Developer Guide: Using $location}\n */\n\n/**\n * @ngdoc provider\n * @name $locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider() {\n var hashPrefix = '',\n html5Mode = {\n enabled: false,\n requireBase: true,\n rewriteLinks: true\n };\n\n /**\n * @ngdoc method\n * @name $locationProvider#hashPrefix\n * @description\n * @param {string=} prefix Prefix for hash part (containing path and search)\n * @returns {*} current value if used as getter or itself (chaining) if used as setter\n */\n this.hashPrefix = function(prefix) {\n if (isDefined(prefix)) {\n hashPrefix = prefix;\n return this;\n } else {\n return hashPrefix;\n }\n };\n\n /**\n * @ngdoc method\n * @name $locationProvider#html5Mode\n * @description\n * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.\n * If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported\n * properties:\n * - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to\n * change urls where supported. Will fall back to hash-prefixed paths in browsers that do not\n * support `pushState`.\n * - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies\n * whether or not a tag is required to be present. If `enabled` and `requireBase` are\n * true, and a base tag is not present, an error will be thrown when `$location` is injected.\n * See the {@link guide/$location $location guide for more information}\n * - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled,\n * enables/disables url rewriting for relative links.\n *\n * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter\n */\n this.html5Mode = function(mode) {\n if (isBoolean(mode)) {\n html5Mode.enabled = mode;\n return this;\n } else if (isObject(mode)) {\n\n if (isBoolean(mode.enabled)) {\n html5Mode.enabled = mode.enabled;\n }\n\n if (isBoolean(mode.requireBase)) {\n html5Mode.requireBase = mode.requireBase;\n }\n\n if (isBoolean(mode.rewriteLinks)) {\n html5Mode.rewriteLinks = mode.rewriteLinks;\n }\n\n return this;\n } else {\n return html5Mode;\n }\n };\n\n /**\n * @ngdoc event\n * @name $location#$locationChangeStart\n * @eventType broadcast on root scope\n * @description\n * Broadcasted before a URL will change.\n *\n * This change can be prevented by calling\n * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more\n * details about event object. Upon successful change\n * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.\n *\n * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when\n * the browser supports the HTML5 History API.\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {string} newUrl New URL\n * @param {string=} oldUrl URL that was before it was changed.\n * @param {string=} newState New history state object\n * @param {string=} oldState History state object that was before it was changed.\n */\n\n /**\n * @ngdoc event\n * @name $location#$locationChangeSuccess\n * @eventType broadcast on root scope\n * @description\n * Broadcasted after a URL was changed.\n *\n * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when\n * the browser supports the HTML5 History API.\n *\n * @param {Object} angularEvent Synthetic event object.\n * @param {string} newUrl New URL\n * @param {string=} oldUrl URL that was before it was changed.\n * @param {string=} newState New history state object\n * @param {string=} oldState History state object that was before it was changed.\n */\n\n this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',\n function($rootScope, $browser, $sniffer, $rootElement, $window) {\n var $location,\n LocationMode,\n baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''\n initialUrl = $browser.url(),\n appBase;\n\n if (html5Mode.enabled) {\n if (!baseHref && html5Mode.requireBase) {\n throw $locationMinErr('nobase',\n \"$location in HTML5 mode requires a tag to be present!\");\n }\n appBase = serverBase(initialUrl) + (baseHref || '/');\n LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;\n } else {\n appBase = stripHash(initialUrl);\n LocationMode = LocationHashbangUrl;\n }\n $location = new LocationMode(appBase, '#' + hashPrefix);\n $location.$$parseLinkUrl(initialUrl, initialUrl);\n\n $location.$$state = $browser.state();\n\n var IGNORE_URI_REGEXP = /^\\s*(javascript|mailto):/i;\n\n function setBrowserUrlWithFallback(url, replace, state) {\n var oldUrl = $location.url();\n var oldState = $location.$$state;\n try {\n $browser.url(url, replace, state);\n\n // Make sure $location.state() returns referentially identical (not just deeply equal)\n // state object; this makes possible quick checking if the state changed in the digest\n // loop. Checking deep equality would be too expensive.\n $location.$$state = $browser.state();\n } catch (e) {\n // Restore old values if pushState fails\n $location.url(oldUrl);\n $location.$$state = oldState;\n\n throw e;\n }\n }\n\n $rootElement.on('click', function(event) {\n // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n // currently we open nice url link and redirect then\n\n if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return;\n\n var elm = jqLite(event.target);\n\n // traverse the DOM up to find first A tag\n while (nodeName_(elm[0]) !== 'a') {\n // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n }\n\n var absHref = elm.prop('href');\n // get the actual href attribute - see\n // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx\n var relHref = elm.attr('href') || elm.attr('xlink:href');\n\n if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {\n // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during\n // an animation.\n absHref = urlResolve(absHref.animVal).href;\n }\n\n // Ignore when url is started with javascript: or mailto:\n if (IGNORE_URI_REGEXP.test(absHref)) return;\n\n if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {\n if ($location.$$parseLinkUrl(absHref, relHref)) {\n // We do a preventDefault for all urls that are part of the angular application,\n // in html5mode and also without, so that we are able to abort navigation without\n // getting double entries in the location history.\n event.preventDefault();\n // update location manually\n if ($location.absUrl() != $browser.url()) {\n $rootScope.$apply();\n // hack to work around FF6 bug 684208 when scenario runner clicks on links\n $window.angular['ff-684208-preventDefault'] = true;\n }\n }\n }\n });\n\n\n // rewrite hashbang url <> html5 url\n if ($location.absUrl() != initialUrl) {\n $browser.url($location.absUrl(), true);\n }\n\n var initializing = true;\n\n // update $location when $browser url changes\n $browser.onUrlChange(function(newUrl, newState) {\n $rootScope.$evalAsync(function() {\n var oldUrl = $location.absUrl();\n var oldState = $location.$$state;\n var defaultPrevented;\n\n $location.$$parse(newUrl);\n $location.$$state = newState;\n\n defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,\n newState, oldState).defaultPrevented;\n\n // if the location was changed by a `$locationChangeStart` handler then stop\n // processing this location change\n if ($location.absUrl() !== newUrl) return;\n\n if (defaultPrevented) {\n $location.$$parse(oldUrl);\n $location.$$state = oldState;\n setBrowserUrlWithFallback(oldUrl, false, oldState);\n } else {\n initializing = false;\n afterLocationChange(oldUrl, oldState);\n }\n });\n if (!$rootScope.$$phase) $rootScope.$digest();\n });\n\n // update browser\n $rootScope.$watch(function $locationWatch() {\n var oldUrl = trimEmptyHash($browser.url());\n var newUrl = trimEmptyHash($location.absUrl());\n var oldState = $browser.state();\n var currentReplace = $location.$$replace;\n var urlOrStateChanged = oldUrl !== newUrl ||\n ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);\n\n if (initializing || urlOrStateChanged) {\n initializing = false;\n\n $rootScope.$evalAsync(function() {\n var newUrl = $location.absUrl();\n var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,\n $location.$$state, oldState).defaultPrevented;\n\n // if the location was changed by a `$locationChangeStart` handler then stop\n // processing this location change\n if ($location.absUrl() !== newUrl) return;\n\n if (defaultPrevented) {\n $location.$$parse(oldUrl);\n $location.$$state = oldState;\n } else {\n if (urlOrStateChanged) {\n setBrowserUrlWithFallback(newUrl, currentReplace,\n oldState === $location.$$state ? null : $location.$$state);\n }\n afterLocationChange(oldUrl, oldState);\n }\n });\n }\n\n $location.$$replace = false;\n\n // we don't need to return anything because $evalAsync will make the digest loop dirty when\n // there is a change\n });\n\n return $location;\n\n function afterLocationChange(oldUrl, oldState) {\n $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl,\n $location.$$state, oldState);\n }\n}];\n}\n\n/**\n * @ngdoc service\n * @name $log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation safely writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * The default is to log `debug` messages. You can use\n * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.\n *\n * @example\n \n \n angular.module('logExample', [])\n .controller('LogController', ['$scope', '$log', function($scope, $log) {\n $scope.$log = $log;\n $scope.message = 'Hello World!';\n }]);\n \n \n
\n

Reload this page with open console, enter text and hit the log button...

\n Message:\n \n \n \n \n \n
\n
\n
\n */\n\n/**\n * @ngdoc provider\n * @name $logProvider\n * @description\n * Use the `$logProvider` to configure how the application logs messages\n */\nfunction $LogProvider() {\n var debug = true,\n self = this;\n\n /**\n * @ngdoc method\n * @name $logProvider#debugEnabled\n * @description\n * @param {boolean=} flag enable or disable debug level messages\n * @returns {*} current value if used as getter or itself (chaining) if used as setter\n */\n this.debugEnabled = function(flag) {\n if (isDefined(flag)) {\n debug = flag;\n return this;\n } else {\n return debug;\n }\n };\n\n this.$get = ['$window', function($window) {\n return {\n /**\n * @ngdoc method\n * @name $log#log\n *\n * @description\n * Write a log message\n */\n log: consoleLog('log'),\n\n /**\n * @ngdoc method\n * @name $log#info\n *\n * @description\n * Write an information message\n */\n info: consoleLog('info'),\n\n /**\n * @ngdoc method\n * @name $log#warn\n *\n * @description\n * Write a warning message\n */\n warn: consoleLog('warn'),\n\n /**\n * @ngdoc method\n * @name $log#error\n *\n * @description\n * Write an error message\n */\n error: consoleLog('error'),\n\n /**\n * @ngdoc method\n * @name $log#debug\n *\n * @description\n * Write a debug message\n */\n debug: (function() {\n var fn = consoleLog('debug');\n\n return function() {\n if (debug) {\n fn.apply(self, arguments);\n }\n };\n }())\n };\n\n function formatError(arg) {\n if (arg instanceof Error) {\n if (arg.stack) {\n arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n ? 'Error: ' + arg.message + '\\n' + arg.stack\n : arg.stack;\n } else if (arg.sourceURL) {\n arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n }\n }\n return arg;\n }\n\n function consoleLog(type) {\n var console = $window.console || {},\n logFn = console[type] || console.log || noop,\n hasApply = false;\n\n // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.\n // The reason behind this is that console.log has type \"object\" in IE8...\n try {\n hasApply = !!logFn.apply;\n } catch (e) {}\n\n if (hasApply) {\n return function() {\n var args = [];\n forEach(arguments, function(arg) {\n args.push(formatError(arg));\n });\n return logFn.apply(console, args);\n };\n }\n\n // we are IE which either doesn't have window.console => this is noop and we do nothing,\n // or we are IE where console.log doesn't have apply so we log at least first 2 args\n return function(arg1, arg2) {\n logFn(arg1, arg2 == null ? '' : arg2);\n };\n }\n }];\n}\n\nvar $parseMinErr = minErr('$parse');\n\n// Sandboxing Angular Expressions\n// ------------------------------\n// Angular expressions are generally considered safe because these expressions only have direct\n// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by\n// obtaining a reference to native JS functions such as the Function constructor.\n//\n// As an example, consider the following Angular expression:\n//\n// {}.toString.constructor('alert(\"evil JS code\")')\n//\n// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits\n// against the expression language, but not to prevent exploits that were enabled by exposing\n// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good\n// practice and therefore we are not even trying to protect against interaction with an object\n// explicitly exposed in this way.\n//\n// In general, it is not possible to access a Window object from an angular expression unless a\n// window or some DOM object that has a reference to window is published onto a Scope.\n// Similarly we prevent invocations of function known to be dangerous, as well as assignments to\n// native objects.\n//\n// See https://docs.angularjs.org/guide/security\n\n\nfunction ensureSafeMemberName(name, fullExpression) {\n if (name === \"__defineGetter__\" || name === \"__defineSetter__\"\n || name === \"__lookupGetter__\" || name === \"__lookupSetter__\"\n || name === \"__proto__\") {\n throw $parseMinErr('isecfld',\n 'Attempting to access a disallowed field in Angular expressions! '\n + 'Expression: {0}', fullExpression);\n }\n return name;\n}\n\nfunction ensureSafeObject(obj, fullExpression) {\n // nifty check if obj is Function that is fast and works across iframes and other contexts\n if (obj) {\n if (obj.constructor === obj) {\n throw $parseMinErr('isecfn',\n 'Referencing Function in Angular expressions is disallowed! Expression: {0}',\n fullExpression);\n } else if (// isWindow(obj)\n obj.window === obj) {\n throw $parseMinErr('isecwindow',\n 'Referencing the Window in Angular expressions is disallowed! Expression: {0}',\n fullExpression);\n } else if (// isElement(obj)\n obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {\n throw $parseMinErr('isecdom',\n 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',\n fullExpression);\n } else if (// block Object so that we can't get hold of dangerous Object.* methods\n obj === Object) {\n throw $parseMinErr('isecobj',\n 'Referencing Object in Angular expressions is disallowed! Expression: {0}',\n fullExpression);\n }\n }\n return obj;\n}\n\nvar CALL = Function.prototype.call;\nvar APPLY = Function.prototype.apply;\nvar BIND = Function.prototype.bind;\n\nfunction ensureSafeFunction(obj, fullExpression) {\n if (obj) {\n if (obj.constructor === obj) {\n throw $parseMinErr('isecfn',\n 'Referencing Function in Angular expressions is disallowed! Expression: {0}',\n fullExpression);\n } else if (obj === CALL || obj === APPLY || obj === BIND) {\n throw $parseMinErr('isecff',\n 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',\n fullExpression);\n }\n }\n}\n\n//Keyword constants\nvar CONSTANTS = createMap();\nforEach({\n 'null': function() { return null; },\n 'true': function() { return true; },\n 'false': function() { return false; },\n 'undefined': function() {}\n}, function(constantGetter, name) {\n constantGetter.constant = constantGetter.literal = constantGetter.sharedGetter = true;\n CONSTANTS[name] = constantGetter;\n});\n\n//Not quite a constant, but can be lex/parsed the same\nCONSTANTS['this'] = function(self) { return self; };\nCONSTANTS['this'].sharedGetter = true;\n\n\n//Operators - will be wrapped by binaryFn/unaryFn/assignment/filter\nvar OPERATORS = extend(createMap(), {\n '+':function(self, locals, a, b) {\n a=a(self, locals); b=b(self, locals);\n if (isDefined(a)) {\n if (isDefined(b)) {\n return a + b;\n }\n return a;\n }\n return isDefined(b) ? b : undefined;},\n '-':function(self, locals, a, b) {\n a=a(self, locals); b=b(self, locals);\n return (isDefined(a) ? a : 0) - (isDefined(b) ? b : 0);\n },\n '*':function(self, locals, a, b) {return a(self, locals) * b(self, locals);},\n '/':function(self, locals, a, b) {return a(self, locals) / b(self, locals);},\n '%':function(self, locals, a, b) {return a(self, locals) % b(self, locals);},\n '===':function(self, locals, a, b) {return a(self, locals) === b(self, locals);},\n '!==':function(self, locals, a, b) {return a(self, locals) !== b(self, locals);},\n '==':function(self, locals, a, b) {return a(self, locals) == b(self, locals);},\n '!=':function(self, locals, a, b) {return a(self, locals) != b(self, locals);},\n '<':function(self, locals, a, b) {return a(self, locals) < b(self, locals);},\n '>':function(self, locals, a, b) {return a(self, locals) > b(self, locals);},\n '<=':function(self, locals, a, b) {return a(self, locals) <= b(self, locals);},\n '>=':function(self, locals, a, b) {return a(self, locals) >= b(self, locals);},\n '&&':function(self, locals, a, b) {return a(self, locals) && b(self, locals);},\n '||':function(self, locals, a, b) {return a(self, locals) || b(self, locals);},\n '!':function(self, locals, a) {return !a(self, locals);},\n\n //Tokenized as operators but parsed as assignment/filters\n '=':true,\n '|':true\n});\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\n\n/////////////////////////////////////////\n\n\n/**\n * @constructor\n */\nvar Lexer = function(options) {\n this.options = options;\n};\n\nLexer.prototype = {\n constructor: Lexer,\n\n lex: function(text) {\n this.text = text;\n this.index = 0;\n this.tokens = [];\n\n while (this.index < this.text.length) {\n var ch = this.text.charAt(this.index);\n if (ch === '\"' || ch === \"'\") {\n this.readString(ch);\n } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {\n this.readNumber();\n } else if (this.isIdent(ch)) {\n this.readIdent();\n } else if (this.is(ch, '(){}[].,;:?')) {\n this.tokens.push({index: this.index, text: ch});\n this.index++;\n } else if (this.isWhitespace(ch)) {\n this.index++;\n } else {\n var ch2 = ch + this.peek();\n var ch3 = ch2 + this.peek(2);\n var op1 = OPERATORS[ch];\n var op2 = OPERATORS[ch2];\n var op3 = OPERATORS[ch3];\n if (op1 || op2 || op3) {\n var token = op3 ? ch3 : (op2 ? ch2 : ch);\n this.tokens.push({index: this.index, text: token, operator: true});\n this.index += token.length;\n } else {\n this.throwError('Unexpected next character ', this.index, this.index + 1);\n }\n }\n }\n return this.tokens;\n },\n\n is: function(ch, chars) {\n return chars.indexOf(ch) !== -1;\n },\n\n peek: function(i) {\n var num = i || 1;\n return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;\n },\n\n isNumber: function(ch) {\n return ('0' <= ch && ch <= '9') && typeof ch === \"string\";\n },\n\n isWhitespace: function(ch) {\n // IE treats non-breaking space as \\u00A0\n return (ch === ' ' || ch === '\\r' || ch === '\\t' ||\n ch === '\\n' || ch === '\\v' || ch === '\\u00A0');\n },\n\n isIdent: function(ch) {\n return ('a' <= ch && ch <= 'z' ||\n 'A' <= ch && ch <= 'Z' ||\n '_' === ch || ch === '$');\n },\n\n isExpOperator: function(ch) {\n return (ch === '-' || ch === '+' || this.isNumber(ch));\n },\n\n throwError: function(error, start, end) {\n end = end || this.index;\n var colStr = (isDefined(start)\n ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']'\n : ' ' + end);\n throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',\n error, colStr, this.text);\n },\n\n readNumber: function() {\n var number = '';\n var start = this.index;\n while (this.index < this.text.length) {\n var ch = lowercase(this.text.charAt(this.index));\n if (ch == '.' || this.isNumber(ch)) {\n number += ch;\n } else {\n var peekCh = this.peek();\n if (ch == 'e' && this.isExpOperator(peekCh)) {\n number += ch;\n } else if (this.isExpOperator(ch) &&\n peekCh && this.isNumber(peekCh) &&\n number.charAt(number.length - 1) == 'e') {\n number += ch;\n } else if (this.isExpOperator(ch) &&\n (!peekCh || !this.isNumber(peekCh)) &&\n number.charAt(number.length - 1) == 'e') {\n this.throwError('Invalid exponent');\n } else {\n break;\n }\n }\n this.index++;\n }\n this.tokens.push({\n index: start,\n text: number,\n constant: true,\n value: Number(number)\n });\n },\n\n readIdent: function() {\n var start = this.index;\n while (this.index < this.text.length) {\n var ch = this.text.charAt(this.index);\n if (!(this.isIdent(ch) || this.isNumber(ch))) {\n break;\n }\n this.index++;\n }\n this.tokens.push({\n index: start,\n text: this.text.slice(start, this.index),\n identifier: true\n });\n },\n\n readString: function(quote) {\n var start = this.index;\n this.index++;\n var string = '';\n var rawString = quote;\n var escape = false;\n while (this.index < this.text.length) {\n var ch = this.text.charAt(this.index);\n rawString += ch;\n if (escape) {\n if (ch === 'u') {\n var hex = this.text.substring(this.index + 1, this.index + 5);\n if (!hex.match(/[\\da-f]{4}/i))\n this.throwError('Invalid unicode escape [\\\\u' + hex + ']');\n this.index += 4;\n string += String.fromCharCode(parseInt(hex, 16));\n } else {\n var rep = ESCAPE[ch];\n string = string + (rep || ch);\n }\n escape = false;\n } else if (ch === '\\\\') {\n escape = true;\n } else if (ch === quote) {\n this.index++;\n this.tokens.push({\n index: start,\n text: rawString,\n constant: true,\n value: string\n });\n return;\n } else {\n string += ch;\n }\n this.index++;\n }\n this.throwError('Unterminated quote', start);\n }\n};\n\n\nfunction isConstant(exp) {\n return exp.constant;\n}\n\n/**\n * @constructor\n */\nvar Parser = function(lexer, $filter, options) {\n this.lexer = lexer;\n this.$filter = $filter;\n this.options = options;\n};\n\nParser.ZERO = extend(function() {\n return 0;\n}, {\n sharedGetter: true,\n constant: true\n});\n\nParser.prototype = {\n constructor: Parser,\n\n parse: function(text) {\n this.text = text;\n this.tokens = this.lexer.lex(text);\n\n var value = this.statements();\n\n if (this.tokens.length !== 0) {\n this.throwError('is an unexpected token', this.tokens[0]);\n }\n\n value.literal = !!value.literal;\n value.constant = !!value.constant;\n\n return value;\n },\n\n primary: function() {\n var primary;\n if (this.expect('(')) {\n primary = this.filterChain();\n this.consume(')');\n } else if (this.expect('[')) {\n primary = this.arrayDeclaration();\n } else if (this.expect('{')) {\n primary = this.object();\n } else if (this.peek().identifier && this.peek().text in CONSTANTS) {\n primary = CONSTANTS[this.consume().text];\n } else if (this.peek().identifier) {\n primary = this.identifier();\n } else if (this.peek().constant) {\n primary = this.constant();\n } else {\n this.throwError('not a primary expression', this.peek());\n }\n\n var next, context;\n while ((next = this.expect('(', '[', '.'))) {\n if (next.text === '(') {\n primary = this.functionCall(primary, context);\n context = null;\n } else if (next.text === '[') {\n context = primary;\n primary = this.objectIndex(primary);\n } else if (next.text === '.') {\n context = primary;\n primary = this.fieldAccess(primary);\n } else {\n this.throwError('IMPOSSIBLE');\n }\n }\n return primary;\n },\n\n throwError: function(msg, token) {\n throw $parseMinErr('syntax',\n 'Syntax Error: Token \\'{0}\\' {1} at column {2} of the expression [{3}] starting at [{4}].',\n token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));\n },\n\n peekToken: function() {\n if (this.tokens.length === 0)\n throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);\n return this.tokens[0];\n },\n\n peek: function(e1, e2, e3, e4) {\n return this.peekAhead(0, e1, e2, e3, e4);\n },\n peekAhead: function(i, e1, e2, e3, e4) {\n if (this.tokens.length > i) {\n var token = this.tokens[i];\n var t = token.text;\n if (t === e1 || t === e2 || t === e3 || t === e4 ||\n (!e1 && !e2 && !e3 && !e4)) {\n return token;\n }\n }\n return false;\n },\n\n expect: function(e1, e2, e3, e4) {\n var token = this.peek(e1, e2, e3, e4);\n if (token) {\n this.tokens.shift();\n return token;\n }\n return false;\n },\n\n consume: function(e1) {\n if (this.tokens.length === 0) {\n throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);\n }\n\n var token = this.expect(e1);\n if (!token) {\n this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());\n }\n return token;\n },\n\n unaryFn: function(op, right) {\n var fn = OPERATORS[op];\n return extend(function $parseUnaryFn(self, locals) {\n return fn(self, locals, right);\n }, {\n constant:right.constant,\n inputs: [right]\n });\n },\n\n binaryFn: function(left, op, right, isBranching) {\n var fn = OPERATORS[op];\n return extend(function $parseBinaryFn(self, locals) {\n return fn(self, locals, left, right);\n }, {\n constant: left.constant && right.constant,\n inputs: !isBranching && [left, right]\n });\n },\n\n identifier: function() {\n var id = this.consume().text;\n\n //Continue reading each `.identifier` unless it is a method invocation\n while (this.peek('.') && this.peekAhead(1).identifier && !this.peekAhead(2, '(')) {\n id += this.consume().text + this.consume().text;\n }\n\n return getterFn(id, this.options, this.text);\n },\n\n constant: function() {\n var value = this.consume().value;\n\n return extend(function $parseConstant() {\n return value;\n }, {\n constant: true,\n literal: true\n });\n },\n\n statements: function() {\n var statements = [];\n while (true) {\n if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))\n statements.push(this.filterChain());\n if (!this.expect(';')) {\n // optimize for the common case where there is only one statement.\n // TODO(size): maybe we should not support multiple statements?\n return (statements.length === 1)\n ? statements[0]\n : function $parseStatements(self, locals) {\n var value;\n for (var i = 0, ii = statements.length; i < ii; i++) {\n value = statements[i](self, locals);\n }\n return value;\n };\n }\n }\n },\n\n filterChain: function() {\n var left = this.expression();\n var token;\n while ((token = this.expect('|'))) {\n left = this.filter(left);\n }\n return left;\n },\n\n filter: function(inputFn) {\n var fn = this.$filter(this.consume().text);\n var argsFn;\n var args;\n\n if (this.peek(':')) {\n argsFn = [];\n args = []; // we can safely reuse the array\n while (this.expect(':')) {\n argsFn.push(this.expression());\n }\n }\n\n var inputs = [inputFn].concat(argsFn || []);\n\n return extend(function $parseFilter(self, locals) {\n var input = inputFn(self, locals);\n if (args) {\n args[0] = input;\n\n var i = argsFn.length;\n while (i--) {\n args[i + 1] = argsFn[i](self, locals);\n }\n\n return fn.apply(undefined, args);\n }\n\n return fn(input);\n }, {\n constant: !fn.$stateful && inputs.every(isConstant),\n inputs: !fn.$stateful && inputs\n });\n },\n\n expression: function() {\n return this.assignment();\n },\n\n assignment: function() {\n var left = this.ternary();\n var right;\n var token;\n if ((token = this.expect('='))) {\n if (!left.assign) {\n this.throwError('implies assignment but [' +\n this.text.substring(0, token.index) + '] can not be assigned to', token);\n }\n right = this.ternary();\n return extend(function $parseAssignment(scope, locals) {\n return left.assign(scope, right(scope, locals), locals);\n }, {\n inputs: [left, right]\n });\n }\n return left;\n },\n\n ternary: function() {\n var left = this.logicalOR();\n var middle;\n var token;\n if ((token = this.expect('?'))) {\n middle = this.assignment();\n if (this.consume(':')) {\n var right = this.assignment();\n\n return extend(function $parseTernary(self, locals) {\n return left(self, locals) ? middle(self, locals) : right(self, locals);\n }, {\n constant: left.constant && middle.constant && right.constant\n });\n }\n }\n\n return left;\n },\n\n logicalOR: function() {\n var left = this.logicalAND();\n var token;\n while ((token = this.expect('||'))) {\n left = this.binaryFn(left, token.text, this.logicalAND(), true);\n }\n return left;\n },\n\n logicalAND: function() {\n var left = this.equality();\n var token;\n while ((token = this.expect('&&'))) {\n left = this.binaryFn(left, token.text, this.equality(), true);\n }\n return left;\n },\n\n equality: function() {\n var left = this.relational();\n var token;\n while ((token = this.expect('==','!=','===','!=='))) {\n left = this.binaryFn(left, token.text, this.relational());\n }\n return left;\n },\n\n relational: function() {\n var left = this.additive();\n var token;\n while ((token = this.expect('<', '>', '<=', '>='))) {\n left = this.binaryFn(left, token.text, this.additive());\n }\n return left;\n },\n\n additive: function() {\n var left = this.multiplicative();\n var token;\n while ((token = this.expect('+','-'))) {\n left = this.binaryFn(left, token.text, this.multiplicative());\n }\n return left;\n },\n\n multiplicative: function() {\n var left = this.unary();\n var token;\n while ((token = this.expect('*','/','%'))) {\n left = this.binaryFn(left, token.text, this.unary());\n }\n return left;\n },\n\n unary: function() {\n var token;\n if (this.expect('+')) {\n return this.primary();\n } else if ((token = this.expect('-'))) {\n return this.binaryFn(Parser.ZERO, token.text, this.unary());\n } else if ((token = this.expect('!'))) {\n return this.unaryFn(token.text, this.unary());\n } else {\n return this.primary();\n }\n },\n\n fieldAccess: function(object) {\n var getter = this.identifier();\n\n return extend(function $parseFieldAccess(scope, locals, self) {\n var o = self || object(scope, locals);\n return (o == null) ? undefined : getter(o);\n }, {\n assign: function(scope, value, locals) {\n var o = object(scope, locals);\n if (!o) object.assign(scope, o = {}, locals);\n return getter.assign(o, value);\n }\n });\n },\n\n objectIndex: function(obj) {\n var expression = this.text;\n\n var indexFn = this.expression();\n this.consume(']');\n\n return extend(function $parseObjectIndex(self, locals) {\n var o = obj(self, locals),\n i = indexFn(self, locals),\n v;\n\n ensureSafeMemberName(i, expression);\n if (!o) return undefined;\n v = ensureSafeObject(o[i], expression);\n return v;\n }, {\n assign: function(self, value, locals) {\n var key = ensureSafeMemberName(indexFn(self, locals), expression);\n // prevent overwriting of Function.constructor which would break ensureSafeObject check\n var o = ensureSafeObject(obj(self, locals), expression);\n if (!o) obj.assign(self, o = {}, locals);\n return o[key] = value;\n }\n });\n },\n\n functionCall: function(fnGetter, contextGetter) {\n var argsFn = [];\n if (this.peekToken().text !== ')') {\n do {\n argsFn.push(this.expression());\n } while (this.expect(','));\n }\n this.consume(')');\n\n var expressionText = this.text;\n // we can safely reuse the array across invocations\n var args = argsFn.length ? [] : null;\n\n return function $parseFunctionCall(scope, locals) {\n var context = contextGetter ? contextGetter(scope, locals) : isDefined(contextGetter) ? undefined : scope;\n var fn = fnGetter(scope, locals, context) || noop;\n\n if (args) {\n var i = argsFn.length;\n while (i--) {\n args[i] = ensureSafeObject(argsFn[i](scope, locals), expressionText);\n }\n }\n\n ensureSafeObject(context, expressionText);\n ensureSafeFunction(fn, expressionText);\n\n // IE doesn't have apply for some native functions\n var v = fn.apply\n ? fn.apply(context, args)\n : fn(args[0], args[1], args[2], args[3], args[4]);\n\n return ensureSafeObject(v, expressionText);\n };\n },\n\n // This is used with json array declaration\n arrayDeclaration: function() {\n var elementFns = [];\n if (this.peekToken().text !== ']') {\n do {\n if (this.peek(']')) {\n // Support trailing commas per ES5.1.\n break;\n }\n elementFns.push(this.expression());\n } while (this.expect(','));\n }\n this.consume(']');\n\n return extend(function $parseArrayLiteral(self, locals) {\n var array = [];\n for (var i = 0, ii = elementFns.length; i < ii; i++) {\n array.push(elementFns[i](self, locals));\n }\n return array;\n }, {\n literal: true,\n constant: elementFns.every(isConstant),\n inputs: elementFns\n });\n },\n\n object: function() {\n var keys = [], valueFns = [];\n if (this.peekToken().text !== '}') {\n do {\n if (this.peek('}')) {\n // Support trailing commas per ES5.1.\n break;\n }\n var token = this.consume();\n if (token.constant) {\n keys.push(token.value);\n } else if (token.identifier) {\n keys.push(token.text);\n } else {\n this.throwError(\"invalid key\", token);\n }\n this.consume(':');\n valueFns.push(this.expression());\n } while (this.expect(','));\n }\n this.consume('}');\n\n return extend(function $parseObjectLiteral(self, locals) {\n var object = {};\n for (var i = 0, ii = valueFns.length; i < ii; i++) {\n object[keys[i]] = valueFns[i](self, locals);\n }\n return object;\n }, {\n literal: true,\n constant: valueFns.every(isConstant),\n inputs: valueFns\n });\n }\n};\n\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, locals, path, setValue, fullExp) {\n ensureSafeObject(obj, fullExp);\n ensureSafeObject(locals, fullExp);\n\n var element = path.split('.'), key;\n for (var i = 0; element.length > 1; i++) {\n key = ensureSafeMemberName(element.shift(), fullExp);\n var propertyObj = (i === 0 && locals && locals[key]) || obj[key];\n if (!propertyObj) {\n propertyObj = {};\n obj[key] = propertyObj;\n }\n obj = ensureSafeObject(propertyObj, fullExp);\n }\n key = ensureSafeMemberName(element.shift(), fullExp);\n ensureSafeObject(obj[key], fullExp);\n obj[key] = setValue;\n return setValue;\n}\n\nvar getterFnCacheDefault = createMap();\nvar getterFnCacheExpensive = createMap();\n\nfunction isPossiblyDangerousMemberName(name) {\n return name == 'constructor';\n}\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, expensiveChecks) {\n ensureSafeMemberName(key0, fullExp);\n ensureSafeMemberName(key1, fullExp);\n ensureSafeMemberName(key2, fullExp);\n ensureSafeMemberName(key3, fullExp);\n ensureSafeMemberName(key4, fullExp);\n var eso = function(o) {\n return ensureSafeObject(o, fullExp);\n };\n var eso0 = (expensiveChecks || isPossiblyDangerousMemberName(key0)) ? eso : identity;\n var eso1 = (expensiveChecks || isPossiblyDangerousMemberName(key1)) ? eso : identity;\n var eso2 = (expensiveChecks || isPossiblyDangerousMemberName(key2)) ? eso : identity;\n var eso3 = (expensiveChecks || isPossiblyDangerousMemberName(key3)) ? eso : identity;\n var eso4 = (expensiveChecks || isPossiblyDangerousMemberName(key4)) ? eso : identity;\n\n return function cspSafeGetter(scope, locals) {\n var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;\n\n if (pathVal == null) return pathVal;\n pathVal = eso0(pathVal[key0]);\n\n if (!key1) return pathVal;\n if (pathVal == null) return undefined;\n pathVal = eso1(pathVal[key1]);\n\n if (!key2) return pathVal;\n if (pathVal == null) return undefined;\n pathVal = eso2(pathVal[key2]);\n\n if (!key3) return pathVal;\n if (pathVal == null) return undefined;\n pathVal = eso3(pathVal[key3]);\n\n if (!key4) return pathVal;\n if (pathVal == null) return undefined;\n pathVal = eso4(pathVal[key4]);\n\n return pathVal;\n };\n}\n\nfunction getterFnWithEnsureSafeObject(fn, fullExpression) {\n return function(s, l) {\n return fn(s, l, ensureSafeObject, fullExpression);\n };\n}\n\nfunction getterFn(path, options, fullExp) {\n var expensiveChecks = options.expensiveChecks;\n var getterFnCache = (expensiveChecks ? getterFnCacheExpensive : getterFnCacheDefault);\n var fn = getterFnCache[path];\n if (fn) return fn;\n\n\n var pathKeys = path.split('.'),\n pathKeysLength = pathKeys.length;\n\n // http://jsperf.com/angularjs-parse-getter/6\n if (options.csp) {\n if (pathKeysLength < 6) {\n fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp, expensiveChecks);\n } else {\n fn = function cspSafeGetter(scope, locals) {\n var i = 0, val;\n do {\n val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],\n pathKeys[i++], fullExp, expensiveChecks)(scope, locals);\n\n locals = undefined; // clear after first iteration\n scope = val;\n } while (i < pathKeysLength);\n return val;\n };\n }\n } else {\n var code = '';\n if (expensiveChecks) {\n code += 's = eso(s, fe);\\nl = eso(l, fe);\\n';\n }\n var needsEnsureSafeObject = expensiveChecks;\n forEach(pathKeys, function(key, index) {\n ensureSafeMemberName(key, fullExp);\n var lookupJs = (index\n // we simply dereference 's' on any .dot notation\n ? 's'\n // but if we are first then we check locals first, and if so read it first\n : '((l&&l.hasOwnProperty(\"' + key + '\"))?l:s)') + '.' + key;\n if (expensiveChecks || isPossiblyDangerousMemberName(key)) {\n lookupJs = 'eso(' + lookupJs + ', fe)';\n needsEnsureSafeObject = true;\n }\n code += 'if(s == null) return undefined;\\n' +\n 's=' + lookupJs + ';\\n';\n });\n code += 'return s;';\n\n /* jshint -W054 */\n var evaledFnGetter = new Function('s', 'l', 'eso', 'fe', code); // s=scope, l=locals, eso=ensureSafeObject\n /* jshint +W054 */\n evaledFnGetter.toString = valueFn(code);\n if (needsEnsureSafeObject) {\n evaledFnGetter = getterFnWithEnsureSafeObject(evaledFnGetter, fullExp);\n }\n fn = evaledFnGetter;\n }\n\n fn.sharedGetter = true;\n fn.assign = function(self, value, locals) {\n return setter(self, locals, path, value, path);\n };\n getterFnCache[path] = fn;\n return fn;\n}\n\nvar objectValueOf = Object.prototype.valueOf;\n\nfunction getValueOf(value) {\n return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc service\n * @name $parse\n * @kind function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * ```js\n * var getter = $parse('user.name');\n * var setter = getter.assign;\n * var context = {user:{name:'angular'}};\n * var locals = {user:{name:'local'}};\n *\n * expect(getter(context)).toEqual('angular');\n * setter(context, 'newValue');\n * expect(context.user.name).toEqual('newValue');\n * expect(getter(context, locals)).toEqual('local');\n * ```\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n * * `context` – `{object}` – an object against which any expressions embedded in the strings\n * are evaluated against (typically a scope object).\n * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n * `context`.\n *\n * The returned function also has the following properties:\n * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript\n * literal.\n * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript\n * constant literals.\n * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be\n * set to a function to change its value on the given context.\n *\n */\n\n\n/**\n * @ngdoc provider\n * @name $parseProvider\n *\n * @description\n * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}\n * service.\n */\nfunction $ParseProvider() {\n var cacheDefault = createMap();\n var cacheExpensive = createMap();\n\n\n\n this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {\n var $parseOptions = {\n csp: $sniffer.csp,\n expensiveChecks: false\n },\n $parseOptionsExpensive = {\n csp: $sniffer.csp,\n expensiveChecks: true\n };\n\n function wrapSharedExpression(exp) {\n var wrapped = exp;\n\n if (exp.sharedGetter) {\n wrapped = function $parseWrapper(self, locals) {\n return exp(self, locals);\n };\n wrapped.literal = exp.literal;\n wrapped.constant = exp.constant;\n wrapped.assign = exp.assign;\n }\n\n return wrapped;\n }\n\n return function $parse(exp, interceptorFn, expensiveChecks) {\n var parsedExpression, oneTime, cacheKey;\n\n switch (typeof exp) {\n case 'string':\n cacheKey = exp = exp.trim();\n\n var cache = (expensiveChecks ? cacheExpensive : cacheDefault);\n parsedExpression = cache[cacheKey];\n\n if (!parsedExpression) {\n if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {\n oneTime = true;\n exp = exp.substring(2);\n }\n\n var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;\n var lexer = new Lexer(parseOptions);\n var parser = new Parser(lexer, $filter, parseOptions);\n parsedExpression = parser.parse(exp);\n\n if (parsedExpression.constant) {\n parsedExpression.$$watchDelegate = constantWatchDelegate;\n } else if (oneTime) {\n //oneTime is not part of the exp passed to the Parser so we may have to\n //wrap the parsedExpression before adding a $$watchDelegate\n parsedExpression = wrapSharedExpression(parsedExpression);\n parsedExpression.$$watchDelegate = parsedExpression.literal ?\n oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;\n } else if (parsedExpression.inputs) {\n parsedExpression.$$watchDelegate = inputsWatchDelegate;\n }\n\n cache[cacheKey] = parsedExpression;\n }\n return addInterceptor(parsedExpression, interceptorFn);\n\n case 'function':\n return addInterceptor(exp, interceptorFn);\n\n default:\n return addInterceptor(noop, interceptorFn);\n }\n };\n\n function collectExpressionInputs(inputs, list) {\n for (var i = 0, ii = inputs.length; i < ii; i++) {\n var input = inputs[i];\n if (!input.constant) {\n if (input.inputs) {\n collectExpressionInputs(input.inputs, list);\n } else if (list.indexOf(input) === -1) { // TODO(perf) can we do better?\n list.push(input);\n }\n }\n }\n\n return list;\n }\n\n function expressionInputDirtyCheck(newValue, oldValueOfValue) {\n\n if (newValue == null || oldValueOfValue == null) { // null/undefined\n return newValue === oldValueOfValue;\n }\n\n if (typeof newValue === 'object') {\n\n // attempt to convert the value to a primitive type\n // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can\n // be cheaply dirty-checked\n newValue = getValueOf(newValue);\n\n if (typeof newValue === 'object') {\n // objects/arrays are not supported - deep-watching them would be too expensive\n return false;\n }\n\n // fall-through to the primitive equality check\n }\n\n //Primitive or NaN\n return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue);\n }\n\n function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n var inputExpressions = parsedExpression.$$inputs ||\n (parsedExpression.$$inputs = collectExpressionInputs(parsedExpression.inputs, []));\n\n var lastResult;\n\n if (inputExpressions.length === 1) {\n var oldInputValue = expressionInputDirtyCheck; // init to something unique so that equals check fails\n inputExpressions = inputExpressions[0];\n return scope.$watch(function expressionInputWatch(scope) {\n var newInputValue = inputExpressions(scope);\n if (!expressionInputDirtyCheck(newInputValue, oldInputValue)) {\n lastResult = parsedExpression(scope);\n oldInputValue = newInputValue && getValueOf(newInputValue);\n }\n return lastResult;\n }, listener, objectEquality);\n }\n\n var oldInputValueOfValues = [];\n for (var i = 0, ii = inputExpressions.length; i < ii; i++) {\n oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails\n }\n\n return scope.$watch(function expressionInputsWatch(scope) {\n var changed = false;\n\n for (var i = 0, ii = inputExpressions.length; i < ii; i++) {\n var newInputValue = inputExpressions[i](scope);\n if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {\n oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);\n }\n }\n\n if (changed) {\n lastResult = parsedExpression(scope);\n }\n\n return lastResult;\n }, listener, objectEquality);\n }\n\n function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n var unwatch, lastValue;\n return unwatch = scope.$watch(function oneTimeWatch(scope) {\n return parsedExpression(scope);\n }, function oneTimeListener(value, old, scope) {\n lastValue = value;\n if (isFunction(listener)) {\n listener.apply(this, arguments);\n }\n if (isDefined(value)) {\n scope.$$postDigest(function() {\n if (isDefined(lastValue)) {\n unwatch();\n }\n });\n }\n }, objectEquality);\n }\n\n function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n var unwatch, lastValue;\n return unwatch = scope.$watch(function oneTimeWatch(scope) {\n return parsedExpression(scope);\n }, function oneTimeListener(value, old, scope) {\n lastValue = value;\n if (isFunction(listener)) {\n listener.call(this, value, old, scope);\n }\n if (isAllDefined(value)) {\n scope.$$postDigest(function() {\n if (isAllDefined(lastValue)) unwatch();\n });\n }\n }, objectEquality);\n\n function isAllDefined(value) {\n var allDefined = true;\n forEach(value, function(val) {\n if (!isDefined(val)) allDefined = false;\n });\n return allDefined;\n }\n }\n\n function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {\n var unwatch;\n return unwatch = scope.$watch(function constantWatch(scope) {\n return parsedExpression(scope);\n }, function constantListener(value, old, scope) {\n if (isFunction(listener)) {\n listener.apply(this, arguments);\n }\n unwatch();\n }, objectEquality);\n }\n\n function addInterceptor(parsedExpression, interceptorFn) {\n if (!interceptorFn) return parsedExpression;\n var watchDelegate = parsedExpression.$$watchDelegate;\n\n var regularWatch =\n watchDelegate !== oneTimeLiteralWatchDelegate &&\n watchDelegate !== oneTimeWatchDelegate;\n\n var fn = regularWatch ? function regularInterceptedExpression(scope, locals) {\n var value = parsedExpression(scope, locals);\n return interceptorFn(value, scope, locals);\n } : function oneTimeInterceptedExpression(scope, locals) {\n var value = parsedExpression(scope, locals);\n var result = interceptorFn(value, scope, locals);\n // we only return the interceptor's result if the\n // initial value is defined (for bind-once)\n return isDefined(value) ? result : value;\n };\n\n // Propagate $$watchDelegates other then inputsWatchDelegate\n if (parsedExpression.$$watchDelegate &&\n parsedExpression.$$watchDelegate !== inputsWatchDelegate) {\n fn.$$watchDelegate = parsedExpression.$$watchDelegate;\n } else if (!interceptorFn.$stateful) {\n // If there is an interceptor, but no watchDelegate then treat the interceptor like\n // we treat filters - it is assumed to be a pure function unless flagged with $stateful\n fn.$$watchDelegate = inputsWatchDelegate;\n fn.inputs = [parsedExpression];\n }\n\n return fn;\n }\n }];\n}\n\n/**\n * @ngdoc service\n * @name $q\n * @requires $rootScope\n *\n * @description\n * A service that helps you run functions asynchronously, and use their return values (or exceptions)\n * when they are done processing.\n *\n * This is an implementation of promises/deferred objects inspired by\n * [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred\n * implementations, and the other which resembles ES6 promises to some degree.\n *\n * # $q constructor\n *\n * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver`\n * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony,\n * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).\n *\n * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are\n * available yet.\n *\n * It can be used like so:\n *\n * ```js\n * // for the purpose of this example let's assume that variables `$q` and `okToGreet`\n * // are available in the current lexical scope (they could have been injected or passed in).\n *\n * function asyncGreet(name) {\n * // perform some asynchronous operation, resolve or reject the promise when appropriate.\n * return $q(function(resolve, reject) {\n * setTimeout(function() {\n * if (okToGreet(name)) {\n * resolve('Hello, ' + name + '!');\n * } else {\n * reject('Greeting ' + name + ' is not allowed.');\n * }\n * }, 1000);\n * });\n * }\n *\n * var promise = asyncGreet('Robin Hood');\n * promise.then(function(greeting) {\n * alert('Success: ' + greeting);\n * }, function(reason) {\n * alert('Failed: ' + reason);\n * });\n * ```\n *\n * Note: progress/notify callbacks are not currently supported via the ES6-style interface.\n *\n * However, the more traditional CommonJS-style usage is still available, and documented below.\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise APIs are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * ```js\n * // for the purpose of this example let's assume that variables `$q` and `okToGreet`\n * // are available in the current lexical scope (they could have been injected or passed in).\n *\n * function asyncGreet(name) {\n * var deferred = $q.defer();\n *\n * setTimeout(function() {\n * deferred.notify('About to greet ' + name + '.');\n *\n * if (okToGreet(name)) {\n * deferred.resolve('Hello, ' + name + '!');\n * } else {\n * deferred.reject('Greeting ' + name + ' is not allowed.');\n * }\n * }, 1000);\n *\n * return deferred.promise;\n * }\n *\n * var promise = asyncGreet('Robin Hood');\n * promise.then(function(greeting) {\n * alert('Success: ' + greeting);\n * }, function(reason) {\n * alert('Failed: ' + reason);\n * }, function(update) {\n * alert('Got notification: ' + update);\n * });\n * ```\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of guarantees that promise and deferred APIs make, see\n * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as APIs\n * that can be used for signaling the successful or unsuccessful completion, as well as the status\n * of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n * constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n * resolving it with a rejection constructed via `$q.reject`.\n * - `notify(value)` - provides updates on the status of the promise's execution. This may be called\n * multiple times before the promise is either resolved or rejected.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or\n * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously\n * as soon as the result is available. The callbacks are called with a single argument: the result\n * or rejection reason. Additionally, the notify callback may be called zero or more times to\n * provide a progress indication, before the promise is resolved or rejected.\n *\n * This method *returns a new promise* which is resolved or rejected via the return value of the\n * `successCallback`, `errorCallback`. It also notifies via the return value of the\n * `notifyCallback` method. The promise cannot be resolved or rejected from the notifyCallback\n * method.\n *\n * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`\n *\n * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise,\n * but to do so without modifying the final value. This is useful to release resources or do some\n * clean-up that needs to be done whether the promise was rejected or resolved. See the [full\n * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for\n * more information.\n *\n * # Chaining promises\n *\n * Because calling the `then` method of a promise returns a new derived promise, it is easily\n * possible to create a chain of promises:\n *\n * ```js\n * promiseB = promiseA.then(function(result) {\n * return result + 1;\n * });\n *\n * // promiseB will be resolved immediately after promiseA is resolved and its value\n * // will be the result of promiseA incremented by 1\n * ```\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful APIs like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n * There are two main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n * mechanism in angular, which means faster propagation of resolution or rejection into your\n * models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains\n * all the important functionality needed for common async tasks.\n *\n * # Testing\n *\n * ```js\n * it('should simulate promise', inject(function($q, $rootScope) {\n * var deferred = $q.defer();\n * var promise = deferred.promise;\n * var resolvedValue;\n *\n * promise.then(function(value) { resolvedValue = value; });\n * expect(resolvedValue).toBeUndefined();\n *\n * // Simulate resolving of promise\n * deferred.resolve(123);\n * // Note that the 'then' function does not get called synchronously.\n * // This is because we want the promise API to always be async, whether or not\n * // it got called synchronously or asynchronously.\n * expect(resolvedValue).toBeUndefined();\n *\n * // Propagate promise resolution to 'then' functions using $apply().\n * $rootScope.$apply();\n * expect(resolvedValue).toEqual(123);\n * }));\n * ```\n *\n * @param {function(function, function)} resolver Function which is responsible for resolving or\n * rejecting the newly created promise. The first parameter is a function which resolves the\n * promise, the second parameter is a function which rejects the promise.\n *\n * @returns {Promise} The newly created promise.\n */\nfunction $QProvider() {\n\n this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n return qFactory(function(callback) {\n $rootScope.$evalAsync(callback);\n }, $exceptionHandler);\n }];\n}\n\nfunction $$QProvider() {\n this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {\n return qFactory(function(callback) {\n $browser.defer(callback);\n }, $exceptionHandler);\n }];\n}\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n * debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n var $qMinErr = minErr('$q', TypeError);\n function callOnce(self, resolveFn, rejectFn) {\n var called = false;\n function wrap(fn) {\n return function(value) {\n if (called) return;\n called = true;\n fn.call(self, value);\n };\n }\n\n return [wrap(resolveFn), wrap(rejectFn)];\n }\n\n /**\n * @ngdoc method\n * @name ng.$q#defer\n * @kind function\n *\n * @description\n * Creates a `Deferred` object which represents a task which will finish in the future.\n *\n * @returns {Deferred} Returns a new instance of deferred.\n */\n var defer = function() {\n return new Deferred();\n };\n\n function Promise() {\n this.$$state = { status: 0 };\n }\n\n Promise.prototype = {\n then: function(onFulfilled, onRejected, progressBack) {\n var result = new Deferred();\n\n this.$$state.pending = this.$$state.pending || [];\n this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);\n if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);\n\n return result.promise;\n },\n\n \"catch\": function(callback) {\n return this.then(null, callback);\n },\n\n \"finally\": function(callback, progressBack) {\n return this.then(function(value) {\n return handleCallback(value, true, callback);\n }, function(error) {\n return handleCallback(error, false, callback);\n }, progressBack);\n }\n };\n\n //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native\n function simpleBind(context, fn) {\n return function(value) {\n fn.call(context, value);\n };\n }\n\n function processQueue(state) {\n var fn, promise, pending;\n\n pending = state.pending;\n state.processScheduled = false;\n state.pending = undefined;\n for (var i = 0, ii = pending.length; i < ii; ++i) {\n promise = pending[i][0];\n fn = pending[i][state.status];\n try {\n if (isFunction(fn)) {\n promise.resolve(fn(state.value));\n } else if (state.status === 1) {\n promise.resolve(state.value);\n } else {\n promise.reject(state.value);\n }\n } catch (e) {\n promise.reject(e);\n exceptionHandler(e);\n }\n }\n }\n\n function scheduleProcessQueue(state) {\n if (state.processScheduled || !state.pending) return;\n state.processScheduled = true;\n nextTick(function() { processQueue(state); });\n }\n\n function Deferred() {\n this.promise = new Promise();\n //Necessary to support unbound execution :/\n this.resolve = simpleBind(this, this.resolve);\n this.reject = simpleBind(this, this.reject);\n this.notify = simpleBind(this, this.notify);\n }\n\n Deferred.prototype = {\n resolve: function(val) {\n if (this.promise.$$state.status) return;\n if (val === this.promise) {\n this.$$reject($qMinErr(\n 'qcycle',\n \"Expected promise to be resolved with value other than itself '{0}'\",\n val));\n }\n else {\n this.$$resolve(val);\n }\n\n },\n\n $$resolve: function(val) {\n var then, fns;\n\n fns = callOnce(this, this.$$resolve, this.$$reject);\n try {\n if ((isObject(val) || isFunction(val))) then = val && val.then;\n if (isFunction(then)) {\n this.promise.$$state.status = -1;\n then.call(val, fns[0], fns[1], this.notify);\n } else {\n this.promise.$$state.value = val;\n this.promise.$$state.status = 1;\n scheduleProcessQueue(this.promise.$$state);\n }\n } catch (e) {\n fns[1](e);\n exceptionHandler(e);\n }\n },\n\n reject: function(reason) {\n if (this.promise.$$state.status) return;\n this.$$reject(reason);\n },\n\n $$reject: function(reason) {\n this.promise.$$state.value = reason;\n this.promise.$$state.status = 2;\n scheduleProcessQueue(this.promise.$$state);\n },\n\n notify: function(progress) {\n var callbacks = this.promise.$$state.pending;\n\n if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) {\n nextTick(function() {\n var callback, result;\n for (var i = 0, ii = callbacks.length; i < ii; i++) {\n result = callbacks[i][0];\n callback = callbacks[i][3];\n try {\n result.notify(isFunction(callback) ? callback(progress) : progress);\n } catch (e) {\n exceptionHandler(e);\n }\n }\n });\n }\n }\n };\n\n /**\n * @ngdoc method\n * @name $q#reject\n * @kind function\n *\n * @description\n * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n * a promise chain, you don't need to worry about it.\n *\n * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n * a promise error callback and you want to forward the error to the promise derived from the\n * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n * `reject`.\n *\n * ```js\n * promiseB = promiseA.then(function(result) {\n * // success: do something and resolve promiseB\n * // with the old or a new result\n * return result;\n * }, function(reason) {\n * // error: handle the error if possible and\n * // resolve promiseB with newPromiseOrValue,\n * // otherwise forward the rejection to promiseB\n * if (canHandle(reason)) {\n * // handle the error and recover\n * return newPromiseOrValue;\n * }\n * return $q.reject(reason);\n * });\n * ```\n *\n * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n */\n var reject = function(reason) {\n var result = new Deferred();\n result.reject(reason);\n return result.promise;\n };\n\n var makePromise = function makePromise(value, resolved) {\n var result = new Deferred();\n if (resolved) {\n result.resolve(value);\n } else {\n result.reject(value);\n }\n return result.promise;\n };\n\n var handleCallback = function handleCallback(value, isResolved, callback) {\n var callbackOutput = null;\n try {\n if (isFunction(callback)) callbackOutput = callback();\n } catch (e) {\n return makePromise(e, false);\n }\n if (isPromiseLike(callbackOutput)) {\n return callbackOutput.then(function() {\n return makePromise(value, isResolved);\n }, function(error) {\n return makePromise(error, false);\n });\n } else {\n return makePromise(value, isResolved);\n }\n };\n\n /**\n * @ngdoc method\n * @name $q#when\n * @kind function\n *\n * @description\n * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n * This is useful when you are dealing with an object that might or might not be a promise, or if\n * the promise comes from a source that can't be trusted.\n *\n * @param {*} value Value or a promise\n * @returns {Promise} Returns a promise of the passed value or promise\n */\n\n\n var when = function(value, callback, errback, progressBack) {\n var result = new Deferred();\n result.resolve(value);\n return result.promise.then(callback, errback, progressBack);\n };\n\n /**\n * @ngdoc method\n * @name $q#all\n * @kind function\n *\n * @description\n * Combines multiple promises into a single promise that is resolved when all of the input\n * promises are resolved.\n *\n * @param {Array.|Object.} promises An array or hash of promises.\n * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,\n * each value corresponding to the promise at the same index/key in the `promises` array/hash.\n * If any of the promises is resolved with a rejection, this resulting promise will be rejected\n * with the same rejection value.\n */\n\n function all(promises) {\n var deferred = new Deferred(),\n counter = 0,\n results = isArray(promises) ? [] : {};\n\n forEach(promises, function(promise, key) {\n counter++;\n when(promise).then(function(value) {\n if (results.hasOwnProperty(key)) return;\n results[key] = value;\n if (!(--counter)) deferred.resolve(results);\n }, function(reason) {\n if (results.hasOwnProperty(key)) return;\n deferred.reject(reason);\n });\n });\n\n if (counter === 0) {\n deferred.resolve(results);\n }\n\n return deferred.promise;\n }\n\n var $Q = function Q(resolver) {\n if (!isFunction(resolver)) {\n throw $qMinErr('norslvr', \"Expected resolverFn, got '{0}'\", resolver);\n }\n\n if (!(this instanceof Q)) {\n // More useful when $Q is the Promise itself.\n return new Q(resolver);\n }\n\n var deferred = new Deferred();\n\n function resolveFn(value) {\n deferred.resolve(value);\n }\n\n function rejectFn(reason) {\n deferred.reject(reason);\n }\n\n resolver(resolveFn, rejectFn);\n\n return deferred.promise;\n };\n\n $Q.defer = defer;\n $Q.reject = reject;\n $Q.when = when;\n $Q.all = all;\n\n return $Q;\n}\n\nfunction $$RAFProvider() { //rAF\n this.$get = ['$window', '$timeout', function($window, $timeout) {\n var requestAnimationFrame = $window.requestAnimationFrame ||\n $window.webkitRequestAnimationFrame;\n\n var cancelAnimationFrame = $window.cancelAnimationFrame ||\n $window.webkitCancelAnimationFrame ||\n $window.webkitCancelRequestAnimationFrame;\n\n var rafSupported = !!requestAnimationFrame;\n var raf = rafSupported\n ? function(fn) {\n var id = requestAnimationFrame(fn);\n return function() {\n cancelAnimationFrame(id);\n };\n }\n : function(fn) {\n var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n return function() {\n $timeout.cancel(timer);\n };\n };\n\n raf.supported = rafSupported;\n\n return raf;\n }];\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope are heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive in terms of speed as well as memory:\n * - No closures, instead use prototypical inheritance for API\n * - Internal state needs to be stored on scope directly, which means that private state is\n * exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n * - this means that in order to keep the same order of execution as addition we have to add\n * items to the array at the beginning (unshift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n * - Using an array would be slow since inserts in middle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc provider\n * @name $rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc method\n * @name $rootScopeProvider#digestTtl\n * @description\n *\n * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * In complex applications it's possible that the dependencies between `$watch`s will result in\n * several digest iterations. However if an application needs more than the default 10 digest\n * iterations for its model to stabilize then you should investigate what is causing the model to\n * continuously change during the digest.\n *\n * Increasing the TTL could have performance implications, so you should not change it without\n * proper justification.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc service\n * @name $rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are descendant scopes of the root scope. Scopes provide separation\n * between the model and the view, via a mechanism for watching the model for changes.\n * They also provide an event emission/broadcast and subscription facility. See the\n * {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider() {\n var TTL = 10;\n var $rootScopeMinErr = minErr('$rootScope');\n var lastDirtyWatch = null;\n var applyAsyncId = null;\n\n this.digestTtl = function(value) {\n if (arguments.length) {\n TTL = value;\n }\n return TTL;\n };\n\n this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',\n function($injector, $exceptionHandler, $parse, $browser) {\n\n /**\n * @ngdoc type\n * @name $rootScope.Scope\n *\n * @description\n * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n * {@link auto.$injector $injector}. Child scopes are created using the\n * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n * compiled HTML template is executed.)\n *\n * Here is a simple scope snippet to show how you can interact with the scope.\n * ```html\n * \n * ```\n *\n * # Inheritance\n * A scope can inherit from a parent scope, as in this example:\n * ```js\n var parent = $rootScope;\n var child = parent.$new();\n\n parent.salutation = \"Hello\";\n expect(child.salutation).toEqual('Hello');\n\n child.salutation = \"Welcome\";\n expect(child.salutation).toEqual('Welcome');\n expect(parent.salutation).toEqual('Hello');\n * ```\n *\n * When interacting with `Scope` in tests, additional helper methods are available on the\n * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional\n * details.\n *\n *\n * @param {Object.=} providers Map of service factory which need to be\n * provided for the current scope. Defaults to {@link ng}.\n * @param {Object.=} instanceCache Provides pre-instantiated services which should\n * append/override services provided by `providers`. This is handy\n * when unit-testing and having the need to override a default\n * service.\n * @returns {Object} Newly created scope.\n *\n */\n function Scope() {\n this.$id = nextUid();\n this.$$phase = this.$parent = this.$$watchers =\n this.$$nextSibling = this.$$prevSibling =\n this.$$childHead = this.$$childTail = null;\n this.$root = this;\n this.$$destroyed = false;\n this.$$listeners = {};\n this.$$listenerCount = {};\n this.$$isolateBindings = null;\n }\n\n /**\n * @ngdoc property\n * @name $rootScope.Scope#$id\n *\n * @description\n * Unique scope ID (monotonically increasing) useful for debugging.\n */\n\n /**\n * @ngdoc property\n * @name $rootScope.Scope#$parent\n *\n * @description\n * Reference to the parent scope.\n */\n\n /**\n * @ngdoc property\n * @name $rootScope.Scope#$root\n *\n * @description\n * Reference to the root scope.\n */\n\n Scope.prototype = {\n constructor: Scope,\n /**\n * @ngdoc method\n * @name $rootScope.Scope#$new\n * @kind function\n *\n * @description\n * Creates a new child {@link ng.$rootScope.Scope scope}.\n *\n * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.\n * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n *\n * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is\n * desired for the scope and its child scopes to be permanently detached from the parent and\n * thus stop participating in model change detection and listener notification by invoking.\n *\n * @param {boolean} isolate If true, then the scope does not prototypically inherit from the\n * parent scope. The scope is isolated, as it can not see parent scope properties.\n * When creating widgets, it is useful for the widget to not accidentally read parent\n * state.\n *\n * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent`\n * of the newly created scope. Defaults to `this` scope if not provided.\n * This is used when creating a transclude scope to correctly place it\n * in the scope hierarchy while maintaining the correct prototypical\n * inheritance.\n *\n * @returns {Object} The newly created child scope.\n *\n */\n $new: function(isolate, parent) {\n var child;\n\n parent = parent || this;\n\n if (isolate) {\n child = new Scope();\n child.$root = this.$root;\n } else {\n // Only create a child scope class if somebody asks for one,\n // but cache it to allow the VM to optimize lookups.\n if (!this.$$ChildScope) {\n this.$$ChildScope = function ChildScope() {\n this.$$watchers = this.$$nextSibling =\n this.$$childHead = this.$$childTail = null;\n this.$$listeners = {};\n this.$$listenerCount = {};\n this.$id = nextUid();\n this.$$ChildScope = null;\n };\n this.$$ChildScope.prototype = this;\n }\n child = new this.$$ChildScope();\n }\n child.$parent = parent;\n child.$$prevSibling = parent.$$childTail;\n if (parent.$$childHead) {\n parent.$$childTail.$$nextSibling = child;\n parent.$$childTail = child;\n } else {\n parent.$$childHead = parent.$$childTail = child;\n }\n\n // When the new scope is not isolated or we inherit from `this`, and\n // the parent scope is destroyed, the property `$$destroyed` is inherited\n // prototypically. In all other cases, this property needs to be set\n // when the parent scope is destroyed.\n // The listener needs to be added after the parent is set\n if (isolate || parent != this) child.$on('$destroy', destroyChild);\n\n return child;\n\n function destroyChild() {\n child.$$destroyed = true;\n }\n },\n\n /**\n * @ngdoc method\n * @name $rootScope.Scope#$watch\n * @kind function\n *\n * @description\n * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n *\n * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest\n * $digest()} and should return the value that will be watched. (Since\n * {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the\n * `watchExpression` can execute multiple times per\n * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n * - The `listener` is called only when the value from the current `watchExpression` and the\n * previous call to `watchExpression` are not equal (with the exception of the initial run,\n * see below). Inequality is determined according to reference inequality,\n * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)\n * via the `!==` Javascript operator, unless `objectEquality == true`\n * (see next point)\n * - When `objectEquality == true`, inequality of the `watchExpression` is determined\n * according to the {@link angular.equals} function. To save the value of the object for\n * later comparison, the {@link angular.copy} function is used. This therefore means that\n * watching complex objects will have adverse memory and performance implications.\n * - The watch `listener` may change the model, which may trigger other `listener`s to fire.\n * This is achieved by rerunning the watchers until no changes are detected. The rerun\n * iteration limit is 10 to prevent an infinite loop deadlock.\n *\n *\n * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a\n * change is detected, be prepared for multiple calls to your listener.)\n *\n * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n * watcher. In rare cases, this is undesirable because the listener is called when the result\n * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n * listener was called due to initialization.\n *\n *\n *\n * # Example\n * ```js\n // let's assume that scope was dependency injected as the $rootScope\n var scope = $rootScope;\n scope.name = 'misko';\n scope.counter = 0;\n\n expect(scope.counter).toEqual(0);\n scope.$watch('name', function(newValue, oldValue) {\n scope.counter = scope.counter + 1;\n });\n expect(scope.counter).toEqual(0);\n\n scope.$digest();\n // the listener is always called during the first $digest loop after it was registered\n expect(scope.counter).toEqual(1);\n\n scope.$digest();\n // but now it will not be called unless the value changes\n expect(scope.counter).toEqual(1);\n\n scope.name = 'adam';\n scope.$digest();\n expect(scope.counter).toEqual(2);\n\n\n\n // Using a function as a watchExpression\n var food;\n scope.foodCounter = 0;\n expect(scope.foodCounter).toEqual(0);\n scope.$watch(\n // This function returns the value being watched. It is called for each turn of the $digest loop\n function() { return food; },\n // This is the change listener, called when the value returned from the above function changes\n function(newValue, oldValue) {\n if ( newValue !== oldValue ) {\n // Only increment the counter if the value changed\n scope.foodCounter = scope.foodCounter + 1;\n }\n }\n );\n // No digest has been run so the counter will be zero\n expect(scope.foodCounter).toEqual(0);\n\n // Run the digest but since food has not changed count will still be zero\n scope.$digest();\n expect(scope.foodCounter).toEqual(0);\n\n // Update food and run digest. Now the counter will increment\n food = 'cheeseburger';\n scope.$digest();\n expect(scope.foodCounter).toEqual(1);\n\n * ```\n *\n *\n *\n * @param {(function()|string)} watchExpression Expression that is evaluated on each\n * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers\n * a call to the `listener`.\n *\n * - `string`: Evaluated as {@link guide/expression expression}\n * - `function(scope)`: called with current `scope` as a parameter.\n * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value\n * of `watchExpression` changes.\n *\n * - `newVal` contains the current value of the `watchExpression`\n * - `oldVal` contains the previous value of the `watchExpression`\n * - `scope` refers to the current scope\n * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of\n * comparing for reference equality.\n * @returns {function()} Returns a deregistration function for this listener.\n */\n $watch: function(watchExp, listener, objectEquality) {\n var get = $parse(watchExp);\n\n if (get.$$watchDelegate) {\n return get.$$watchDelegate(this, listener, objectEquality, get);\n }\n var scope = this,\n array = scope.$$watchers,\n watcher = {\n fn: listener,\n last: initWatchVal,\n get: get,\n exp: watchExp,\n eq: !!objectEquality\n };\n\n lastDirtyWatch = null;\n\n if (!isFunction(listener)) {\n watcher.fn = noop;\n }\n\n if (!array) {\n array = scope.$$watchers = [];\n }\n // we use unshift since we use a while loop in $digest for speed.\n // the while loop reads in reverse order.\n array.unshift(watcher);\n\n return function deregisterWatch() {\n arrayRemove(array, watcher);\n lastDirtyWatch = null;\n };\n },\n\n /**\n * @ngdoc method\n * @name $rootScope.Scope#$watchGroup\n * @kind function\n *\n * @description\n * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.\n * If any one expression in the collection changes the `listener` is executed.\n *\n * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every\n * call to $digest() to see if any items changes.\n * - The `listener` is called whenever any expression in the `watchExpressions` array changes.\n *\n * @param {Array.} watchExpressions Array of expressions that will be individually\n * watched using {@link ng.$rootScope.Scope#$watch $watch()}\n *\n * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any\n * expression in `watchExpressions` changes\n * The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching\n * those of `watchExpression`\n * and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching\n * those of `watchExpression`\n * The `scope` refers to the current scope.\n * @returns {function()} Returns a de-registration function for all listeners.\n */\n $watchGroup: function(watchExpressions, listener) {\n var oldValues = new Array(watchExpressions.length);\n var newValues = new Array(watchExpressions.length);\n var deregisterFns = [];\n var self = this;\n var changeReactionScheduled = false;\n var firstRun = true;\n\n if (!watchExpressions.length) {\n // No expressions means we call the listener ASAP\n var shouldCall = true;\n self.$evalAsync(function() {\n if (shouldCall) listener(newValues, newValues, self);\n });\n return function deregisterWatchGroup() {\n shouldCall = false;\n };\n }\n\n if (watchExpressions.length === 1) {\n // Special case size of one\n return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {\n newValues[0] = value;\n oldValues[0] = oldValue;\n listener(newValues, (value === oldValue) ? newValues : oldValues, scope);\n });\n }\n\n forEach(watchExpressions, function(expr, i) {\n var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {\n newValues[i] = value;\n oldValues[i] = oldValue;\n if (!changeReactionScheduled) {\n changeReactionScheduled = true;\n self.$evalAsync(watchGroupAction);\n }\n });\n deregisterFns.push(unwatchFn);\n });\n\n function watchGroupAction() {\n changeReactionScheduled = false;\n\n if (firstRun) {\n firstRun = false;\n listener(newValues, newValues, self);\n } else {\n listener(newValues, oldValues, self);\n }\n }\n\n return function deregisterWatchGroup() {\n while (deregisterFns.length) {\n deregisterFns.shift()();\n }\n };\n },\n\n\n /**\n * @ngdoc method\n * @name $rootScope.Scope#$watchCollection\n * @kind function\n *\n * @description\n * Shallow watches the properties of an object and fires whenever any of the properties change\n * (for arrays, this implies watching the array items; for object maps, this implies watching\n * the properties). If a change is detected, the `listener` callback is fired.\n *\n * - The `obj` collection is observed via standard $watch operation and is examined on every\n * call to $digest() to see if any items have been added, removed, or moved.\n * - The `listener` is called whenever anything within the `obj` has changed. Examples include\n * adding, removing, and moving items belonging to an object or array.\n *\n *\n * # Example\n * ```js\n $scope.names = ['igor', 'matias', 'misko', 'james'];\n $scope.dataCount = 4;\n\n $scope.$watchCollection('names', function(newNames, oldNames) {\n $scope.dataCount = newNames.length;\n });\n\n expect($scope.dataCount).toEqual(4);\n $scope.$digest();\n\n //still at 4 ... no changes\n expect($scope.dataCount).toEqual(4);\n\n $scope.names.pop();\n $scope.$digest();\n\n //now there's been a change\n expect($scope.dataCount).toEqual(3);\n * ```\n *\n *\n * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The\n * expression value should evaluate to an object or an array which is observed on each\n * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the\n * collection will trigger a call to the `listener`.\n *\n * @param {function(newCollection, oldCollection, scope)} listener a callback function called\n * when a change is detected.\n * - The `newCollection` object is the newly modified data obtained from the `obj` expression\n * - The `oldCollection` object is a copy of the former collection data.\n * Due to performance considerations, the`oldCollection` value is computed only if the\n * `listener` function declares two or more arguments.\n * - The `scope` argument refers to the current scope.\n *\n * @returns {function()} Returns a de-registration function for this listener. When the\n * de-registration function is executed, the internal watch operation is terminated.\n */\n $watchCollection: function(obj, listener) {\n $watchCollectionInterceptor.$stateful = true;\n\n var self = this;\n // the current value, updated on each dirty-check run\n var newValue;\n // a shallow copy of the newValue from the last dirty-check run,\n // updated to match newValue during dirty-check run\n var oldValue;\n // a shallow copy of the newValue from when the last change happened\n var veryOldValue;\n // only track veryOldValue if the listener is asking for it\n var trackVeryOldValue = (listener.length > 1);\n var changeDetected = 0;\n var changeDetector = $parse(obj, $watchCollectionInterceptor);\n var internalArray = [];\n var internalObject = {};\n var initRun = true;\n var oldLength = 0;\n\n function $watchCollectionInterceptor(_value) {\n newValue = _value;\n var newLength, key, bothNaN, newItem, oldItem;\n\n // If the new value is undefined, then return undefined as the watch may be a one-time watch\n if (isUndefined(newValue)) return;\n\n if (!isObject(newValue)) { // if primitive\n if (oldValue !== newValue) {\n oldValue = newValue;\n changeDetected++;\n }\n } else if (isArrayLike(newValue)) {\n if (oldValue !== internalArray) {\n // we are transitioning from something which was not an array into array.\n oldValue = internalArray;\n oldLength = oldValue.length = 0;\n changeDetected++;\n }\n\n newLength = newValue.length;\n\n if (oldLength !== newLength) {\n // if lengths do not match we need to trigger change notification\n changeDetected++;\n oldValue.length = oldLength = newLength;\n }\n // copy the items to oldValue and look for changes.\n for (var i = 0; i < newLength; i++) {\n oldItem = oldValue[i];\n newItem = newValue[i];\n\n bothNaN = (oldItem !== oldItem) && (newItem !== newItem);\n if (!bothNaN && (oldItem !== newItem)) {\n changeDetected++;\n oldValue[i] = newItem;\n }\n }\n } else {\n if (oldValue !== internalObject) {\n // we are transitioning from something which was not an object into object.\n oldValue = internalObject = {};\n oldLength = 0;\n changeDetected++;\n }\n // copy the items to oldValue and look for changes.\n newLength = 0;\n for (key in newValue) {\n if (newValue.hasOwnProperty(key)) {\n newLength++;\n newItem = newValue[key];\n oldItem = oldValue[key];\n\n if (key in oldValue) {\n bothNaN = (oldItem !== oldItem) && (newItem !== newItem);\n if (!bothNaN && (oldItem !== newItem)) {\n changeDetected++;\n oldValue[key] = newItem;\n }\n } else {\n oldLength++;\n oldValue[key] = newItem;\n changeDetected++;\n }\n }\n }\n if (oldLength > newLength) {\n // we used to have more keys, need to find them and destroy them.\n changeDetected++;\n for (key in oldValue) {\n if (!newValue.hasOwnProperty(key)) {\n oldLength--;\n delete oldValue[key];\n }\n }\n }\n }\n return changeDetected;\n }\n\n function $watchCollectionAction() {\n if (initRun) {\n initRun = false;\n listener(newValue, newValue, self);\n } else {\n listener(newValue, veryOldValue, self);\n }\n\n // make a copy for the next time a collection is changed\n if (trackVeryOldValue) {\n if (!isObject(newValue)) {\n //primitive\n veryOldValue = newValue;\n } else if (isArrayLike(newValue)) {\n veryOldValue = new Array(newValue.length);\n for (var i = 0; i < newValue.length; i++) {\n veryOldValue[i] = newValue[i];\n }\n } else { // if object\n veryOldValue = {};\n for (var key in newValue) {\n if (hasOwnProperty.call(newValue, key)) {\n veryOldValue[key] = newValue[key];\n }\n }\n }\n }\n }\n\n return this.$watch(changeDetector, $watchCollectionAction);\n },\n\n /**\n * @ngdoc method\n * @name $rootScope.Scope#$digest\n * @kind function\n *\n * @description\n * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and\n * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change\n * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}\n * until no more listeners are firing. This means that it is possible to get into an infinite\n * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of\n * iterations exceeds 10.\n *\n * Usually, you don't call `$digest()` directly in\n * {@link ng.directive:ngController controllers} or in\n * {@link ng.$compileProvider#directive directives}.\n * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within\n * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`.\n *\n * If you want to be notified whenever `$digest()` is called,\n * you can register a `watchExpression` function with\n * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.\n *\n * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.\n *\n * # Example\n * ```js\n var scope = ...;\n scope.name = 'misko';\n scope.counter = 0;\n\n expect(scope.counter).toEqual(0);\n scope.$watch('name', function(newValue, oldValue) {\n scope.counter = scope.counter + 1;\n });\n expect(scope.counter).toEqual(0);\n\n scope.$digest();\n // the listener is always called during the first $digest loop after it was registered\n expect(scope.counter).toEqual(1);\n\n scope.$digest();\n // but now it will not be called unless the value changes\n expect(scope.counter).toEqual(1);\n\n scope.name = 'adam';\n scope.$digest();\n expect(scope.counter).toEqual(2);\n * ```\n *\n */\n $digest: function() {\n var watch, value, last,\n watchers,\n length,\n dirty, ttl = TTL,\n next, current, target = this,\n watchLog = [],\n logIdx, logMsg, asyncTask;\n\n beginPhase('$digest');\n // Check for changes to browser url that happened in sync before the call to $digest\n $browser.$$checkUrlChange();\n\n if (this === $rootScope && applyAsyncId !== null) {\n // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then\n // cancel the scheduled $apply and flush the queue of expressions to be evaluated.\n $browser.defer.cancel(applyAsyncId);\n flushApplyAsync();\n }\n\n lastDirtyWatch = null;\n\n do { // \"while dirty\" loop\n dirty = false;\n current = target;\n\n while (asyncQueue.length) {\n try {\n asyncTask = asyncQueue.shift();\n asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);\n } catch (e) {\n $exceptionHandler(e);\n }\n lastDirtyWatch = null;\n }\n\n traverseScopesLoop:\n do { // \"traverse the scopes\" loop\n if ((watchers = current.$$watchers)) {\n // process our watches\n length = watchers.length;\n while (length--) {\n try {\n watch = watchers[length];\n // Most common watches are on primitives, in which case we can short\n // circuit it with === operator, only when === fails do we use .equals\n if (watch) {\n if ((value = watch.get(current)) !== (last = watch.last) &&\n !(watch.eq\n ? equals(value, last)\n : (typeof value === 'number' && typeof last === 'number'\n && isNaN(value) && isNaN(last)))) {\n dirty = true;\n lastDirtyWatch = watch;\n watch.last = watch.eq ? copy(value, null) : value;\n watch.fn(value, ((last === initWatchVal) ? value : last), current);\n if (ttl < 5) {\n logIdx = 4 - ttl;\n if (!watchLog[logIdx]) watchLog[logIdx] = [];\n watchLog[logIdx].push({\n msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,\n newVal: value,\n oldVal: last\n });\n }\n } else if (watch === lastDirtyWatch) {\n // If the most recently dirty watcher is now clean, short circuit since the remaining watchers\n // have already been tested.\n dirty = false;\n break traverseScopesLoop;\n }\n }\n } catch (e) {\n $exceptionHandler(e);\n }\n }\n }\n\n // Insanity Warning: scope depth-first traversal\n // yes, this code is a bit crazy, but it works and we have tests to prove it!\n // this piece should be kept in sync with the traversal in $broadcast\n if (!(next = (current.$$childHead ||\n (current !== target && current.$$nextSibling)))) {\n while (current !== target && !(next = current.$$nextSibling)) {\n current = current.$parent;\n }\n }\n } while ((current = next));\n\n // `break traverseScopesLoop;` takes us to here\n\n if ((dirty || asyncQueue.length) && !(ttl--)) {\n clearPhase();\n throw $rootScopeMinErr('infdig',\n '{0} $digest() iterations reached. Aborting!\\n' +\n 'Watchers fired in the last 5 iterations: {1}',\n TTL, watchLog);\n }\n\n } while (dirty || asyncQueue.length);\n\n clearPhase();\n\n while (postDigestQueue.length) {\n try {\n postDigestQueue.shift()();\n } catch (e) {\n $exceptionHandler(e);\n }\n }\n },\n\n\n /**\n * @ngdoc event\n * @name $rootScope.Scope#$destroy\n * @eventType broadcast on scope being destroyed\n *\n * @description\n * Broadcasted when a scope and its children are being destroyed.\n *\n * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n * clean up DOM bindings before an element is removed from the DOM.\n */\n\n /**\n * @ngdoc method\n * @name $rootScope.Scope#$destroy\n * @kind function\n *\n * @description\n * Removes the current scope (and all of its children) from the parent scope. Removal implies\n * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n * propagate to the current scope and its children. Removal also implies that the current\n * scope is eligible for garbage collection.\n *\n * The `$destroy()` is usually used by directives such as\n * {@link ng.directive:ngRepeat ngRepeat} for managing the\n * unrolling of the loop.\n *\n * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.\n * Application code can register a `$destroy` event handler that will give it a chance to\n * perform any necessary cleanup.\n *\n * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n * clean up DOM bindings before an element is removed from the DOM.\n */\n $destroy: function() {\n // we can't destroy the root scope or a scope that has been already destroyed\n if (this.$$destroyed) return;\n var parent = this.$parent;\n\n this.$broadcast('$destroy');\n this.$$destroyed = true;\n if (this === $rootScope) return;\n\n for (var eventName in this.$$listenerCount) {\n decrementListenerCount(this, this.$$listenerCount[eventName], eventName);\n }\n\n // sever all the references to parent scopes (after this cleanup, the current scope should\n // not be retained by any of our references and should be eligible for garbage collection)\n if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n // Disable listeners, watchers and apply/digest methods\n this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop;\n this.$on = this.$watch = this.$watchGroup = function() { return noop; };\n this.$$listeners = {};\n\n // All of the code below is bogus code that works around V8's memory leak via optimized code\n // and inline caches.\n //\n // see:\n // - https://code.google.com/p/v8/issues/detail?id=2073#c26\n // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909\n // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n\n this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n this.$$childTail = this.$root = this.$$watchers = null;\n },\n\n /**\n * @ngdoc method\n * @name $rootScope.Scope#$eval\n * @kind function\n *\n * @description\n * Executes the `expression` on the current scope and returns the result. Any exceptions in\n * the expression are propagated (uncaught). This is useful when evaluating Angular\n * expressions.\n *\n * # Example\n * ```js\n var scope = ng.$rootScope.Scope();\n scope.a = 1;\n scope.b = 2;\n\n expect(scope.$eval('a+b')).toEqual(3);\n expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n * ```\n *\n * @param {(string|function())=} expression An angular expression to be executed.\n *\n * - `string`: execute using the rules as defined in {@link guide/expression expression}.\n * - `function(scope)`: execute the function with the current `scope` parameter.\n *\n * @param {(object)=} locals Local variables object, useful for overriding values in scope.\n * @returns {*} The result of evaluating the expression.\n */\n $eval: function(expr, locals) {\n return $parse(expr)(this, locals);\n },\n\n /**\n * @ngdoc method\n * @name $rootScope.Scope#$evalAsync\n * @kind function\n *\n * @description\n * Executes the expression on the current scope at a later point in time.\n *\n * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only\n * that:\n *\n * - it will execute after the function that scheduled the evaluation (preferably before DOM\n * rendering).\n * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n * `expression` execution.\n *\n * Any exceptions from the execution of the expression are forwarded to the\n * {@link ng.$exceptionHandler $exceptionHandler} service.\n *\n * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle\n * will be scheduled. However, it is encouraged to always call code that changes the model\n * from within an `$apply` call. That includes code evaluated via `$evalAsync`.\n *\n * @param {(string|function())=} expression An angular expression to be executed.\n *\n * - `string`: execute using the rules as defined in {@link guide/expression expression}.\n * - `function(scope)`: execute the function with the current `scope` parameter.\n *\n * @param {(object)=} locals Local variables object, useful for overriding values in scope.\n */\n $evalAsync: function(expr, locals) {\n // if we are outside of an $digest loop and this is the first time we are scheduling async\n // task also schedule async auto-flush\n if (!$rootScope.$$phase && !asyncQueue.length) {\n $browser.defer(function() {\n if (asyncQueue.length) {\n $rootScope.$digest();\n }\n });\n }\n\n asyncQueue.push({scope: this, expression: expr, locals: locals});\n },\n\n $$postDigest: function(fn) {\n postDigestQueue.push(fn);\n },\n\n /**\n * @ngdoc method\n * @name $rootScope.Scope#$apply\n * @kind function\n *\n * @description\n * `$apply()` is used to execute an expression in angular from outside of the angular\n * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).\n * Because we are calling into the angular framework we need to perform proper scope life\n * cycle of {@link ng.$exceptionHandler exception handling},\n * {@link ng.$rootScope.Scope#$digest executing watches}.\n *\n * ## Life cycle\n *\n * # Pseudo-Code of `$apply()`\n * ```js\n function $apply(expr) {\n try {\n return $eval(expr);\n } catch (e) {\n $exceptionHandler(e);\n } finally {\n $root.$digest();\n }\n }\n * ```\n *\n *\n * Scope's `$apply()` method transitions through the following stages:\n *\n * 1. The {@link guide/expression expression} is executed using the\n * {@link ng.$rootScope.Scope#$eval $eval()} method.\n * 2. Any exceptions from the execution of the expression are forwarded to the\n * {@link ng.$exceptionHandler $exceptionHandler} service.\n * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the\n * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n *\n *\n * @param {(string|function())=} exp An angular expression to be executed.\n *\n * - `string`: execute using the rules as defined in {@link guide/expression expression}.\n * - `function(scope)`: execute the function with current `scope` parameter.\n *\n * @returns {*} The result of evaluating the expression.\n */\n $apply: function(expr) {\n try {\n beginPhase('$apply');\n return this.$eval(expr);\n } catch (e) {\n $exceptionHandler(e);\n } finally {\n clearPhase();\n try {\n $rootScope.$digest();\n } catch (e) {\n $exceptionHandler(e);\n throw e;\n }\n }\n },\n\n /**\n * @ngdoc method\n * @name $rootScope.Scope#$applyAsync\n * @kind function\n *\n * @description\n * Schedule the invocation of $apply to occur at a later time. The actual time difference\n * varies across browsers, but is typically around ~10 milliseconds.\n *\n * This can be used to queue up multiple expressions which need to be evaluated in the same\n * digest.\n *\n * @param {(string|function())=} exp An angular expression to be executed.\n *\n * - `string`: execute using the rules as defined in {@link guide/expression expression}.\n * - `function(scope)`: execute the function with current `scope` parameter.\n */\n $applyAsync: function(expr) {\n var scope = this;\n expr && applyAsyncQueue.push($applyAsyncExpression);\n scheduleApplyAsync();\n\n function $applyAsyncExpression() {\n scope.$eval(expr);\n }\n },\n\n /**\n * @ngdoc method\n * @name $rootScope.Scope#$on\n * @kind function\n *\n * @description\n * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for\n * discussion of event life cycle.\n *\n * The event listener function format is: `function(event, args...)`. The `event` object\n * passed into the listener has the following attributes:\n *\n * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or\n * `$broadcast`-ed.\n * - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the\n * event propagates through the scope hierarchy, this property is set to null.\n * - `name` - `{string}`: name of the event.\n * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel\n * further event propagation (available only for events that were `$emit`-ed).\n * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag\n * to true.\n * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n *\n * @param {string} name Event name to listen on.\n * @param {function(event, ...args)} listener Function to call when the event is emitted.\n * @returns {function()} Returns a deregistration function for this listener.\n */\n $on: function(name, listener) {\n var namedListeners = this.$$listeners[name];\n if (!namedListeners) {\n this.$$listeners[name] = namedListeners = [];\n }\n namedListeners.push(listener);\n\n var current = this;\n do {\n if (!current.$$listenerCount[name]) {\n current.$$listenerCount[name] = 0;\n }\n current.$$listenerCount[name]++;\n } while ((current = current.$parent));\n\n var self = this;\n return function() {\n var indexOfListener = namedListeners.indexOf(listener);\n if (indexOfListener !== -1) {\n namedListeners[indexOfListener] = null;\n decrementListenerCount(self, 1, name);\n }\n };\n },\n\n\n /**\n * @ngdoc method\n * @name $rootScope.Scope#$emit\n * @kind function\n *\n * @description\n * Dispatches an event `name` upwards through the scope hierarchy notifying the\n * registered {@link ng.$rootScope.Scope#$on} listeners.\n *\n * The event life cycle starts at the scope on which `$emit` was called. All\n * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n * notified. Afterwards, the event traverses upwards toward the root scope and calls all\n * registered listeners along the way. The event will stop propagating if one of the listeners\n * cancels it.\n *\n * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n *\n * @param {string} name Event name to emit.\n * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).\n */\n $emit: function(name, args) {\n var empty = [],\n namedListeners,\n scope = this,\n stopPropagation = false,\n event = {\n name: name,\n targetScope: scope,\n stopPropagation: function() {stopPropagation = true;},\n preventDefault: function() {\n event.defaultPrevented = true;\n },\n defaultPrevented: false\n },\n listenerArgs = concat([event], arguments, 1),\n i, length;\n\n do {\n namedListeners = scope.$$listeners[name] || empty;\n event.currentScope = scope;\n for (i = 0, length = namedListeners.length; i < length; i++) {\n\n // if listeners were deregistered, defragment the array\n if (!namedListeners[i]) {\n namedListeners.splice(i, 1);\n i--;\n length--;\n continue;\n }\n try {\n //allow all listeners attached to the current scope to run\n namedListeners[i].apply(null, listenerArgs);\n } catch (e) {\n $exceptionHandler(e);\n }\n }\n //if any listener on the current scope stops propagation, prevent bubbling\n if (stopPropagation) {\n event.currentScope = null;\n return event;\n }\n //traverse upwards\n scope = scope.$parent;\n } while (scope);\n\n event.currentScope = null;\n\n return event;\n },\n\n\n /**\n * @ngdoc method\n * @name $rootScope.Scope#$broadcast\n * @kind function\n *\n * @description\n * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n * registered {@link ng.$rootScope.Scope#$on} listeners.\n *\n * The event life cycle starts at the scope on which `$broadcast` was called. All\n * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n * notified. Afterwards, the event propagates to all direct and indirect scopes of the current\n * scope and calls all registered listeners along the way. The event cannot be canceled.\n *\n * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n *\n * @param {string} name Event name to broadcast.\n * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n */\n $broadcast: function(name, args) {\n var target = this,\n current = target,\n next = target,\n event = {\n name: name,\n targetScope: target,\n preventDefault: function() {\n event.defaultPrevented = true;\n },\n defaultPrevented: false\n };\n\n if (!target.$$listenerCount[name]) return event;\n\n var listenerArgs = concat([event], arguments, 1),\n listeners, i, length;\n\n //down while you can, then up and next sibling or up and next sibling until back at root\n while ((current = next)) {\n event.currentScope = current;\n listeners = current.$$listeners[name] || [];\n for (i = 0, length = listeners.length; i < length; i++) {\n // if listeners were deregistered, defragment the array\n if (!listeners[i]) {\n listeners.splice(i, 1);\n i--;\n length--;\n continue;\n }\n\n try {\n listeners[i].apply(null, listenerArgs);\n } catch (e) {\n $exceptionHandler(e);\n }\n }\n\n // Insanity Warning: scope depth-first traversal\n // yes, this code is a bit crazy, but it works and we have tests to prove it!\n // this piece should be kept in sync with the traversal in $digest\n // (though it differs due to having the extra check for $$listenerCount)\n if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||\n (current !== target && current.$$nextSibling)))) {\n while (current !== target && !(next = current.$$nextSibling)) {\n current = current.$parent;\n }\n }\n }\n\n event.currentScope = null;\n return event;\n }\n };\n\n var $rootScope = new Scope();\n\n //The internal queues. Expose them on the $rootScope for debugging/testing purposes.\n var asyncQueue = $rootScope.$$asyncQueue = [];\n var postDigestQueue = $rootScope.$$postDigestQueue = [];\n var applyAsyncQueue = $rootScope.$$applyAsyncQueue = [];\n\n return $rootScope;\n\n\n function beginPhase(phase) {\n if ($rootScope.$$phase) {\n throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);\n }\n\n $rootScope.$$phase = phase;\n }\n\n function clearPhase() {\n $rootScope.$$phase = null;\n }\n\n\n function decrementListenerCount(current, count, name) {\n do {\n current.$$listenerCount[name] -= count;\n\n if (current.$$listenerCount[name] === 0) {\n delete current.$$listenerCount[name];\n }\n } while ((current = current.$parent));\n }\n\n /**\n * function used as an initial value for watchers.\n * because it's unique we can easily tell it apart from other values\n */\n function initWatchVal() {}\n\n function flushApplyAsync() {\n while (applyAsyncQueue.length) {\n try {\n applyAsyncQueue.shift()();\n } catch (e) {\n $exceptionHandler(e);\n }\n }\n applyAsyncId = null;\n }\n\n function scheduleApplyAsync() {\n if (applyAsyncId === null) {\n applyAsyncId = $browser.defer(function() {\n $rootScope.$apply(flushApplyAsync);\n });\n }\n }\n }];\n}\n\n/**\n * @description\n * Private service to sanitize uris for links and images. Used by $compile and $sanitize.\n */\nfunction $$SanitizeUriProvider() {\n var aHrefSanitizationWhitelist = /^\\s*(https?|ftp|mailto|tel|file):/,\n imgSrcSanitizationWhitelist = /^\\s*((https?|ftp|file|blob):|data:image\\/)/;\n\n /**\n * @description\n * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n * urls during a[href] sanitization.\n *\n * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n *\n * Any url about to be assigned to a[href] via data-binding is first normalized and turned into\n * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`\n * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n *\n * @param {RegExp=} regexp New regexp to whitelist urls with.\n * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n * chaining otherwise.\n */\n this.aHrefSanitizationWhitelist = function(regexp) {\n if (isDefined(regexp)) {\n aHrefSanitizationWhitelist = regexp;\n return this;\n }\n return aHrefSanitizationWhitelist;\n };\n\n\n /**\n * @description\n * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n * urls during img[src] sanitization.\n *\n * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n *\n * Any url about to be assigned to img[src] via data-binding is first normalized and turned into\n * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`\n * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n *\n * @param {RegExp=} regexp New regexp to whitelist urls with.\n * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n * chaining otherwise.\n */\n this.imgSrcSanitizationWhitelist = function(regexp) {\n if (isDefined(regexp)) {\n imgSrcSanitizationWhitelist = regexp;\n return this;\n }\n return imgSrcSanitizationWhitelist;\n };\n\n this.$get = function() {\n return function sanitizeUri(uri, isImage) {\n var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;\n var normalizedVal;\n normalizedVal = urlResolve(uri).href;\n if (normalizedVal !== '' && !normalizedVal.match(regex)) {\n return 'unsafe:' + normalizedVal;\n }\n return uri;\n };\n };\n}\n\nvar $sceMinErr = minErr('$sce');\n\nvar SCE_CONTEXTS = {\n HTML: 'html',\n CSS: 'css',\n URL: 'url',\n // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a\n // url. (e.g. ng-include, script src, templateUrl)\n RESOURCE_URL: 'resourceUrl',\n JS: 'js'\n};\n\n// Helper functions follow.\n\nfunction adjustMatcher(matcher) {\n if (matcher === 'self') {\n return matcher;\n } else if (isString(matcher)) {\n // Strings match exactly except for 2 wildcards - '*' and '**'.\n // '*' matches any character except those from the set ':/.?&'.\n // '**' matches any character (like .* in a RegExp).\n // More than 2 *'s raises an error as it's ill defined.\n if (matcher.indexOf('***') > -1) {\n throw $sceMinErr('iwcard',\n 'Illegal sequence *** in string matcher. String: {0}', matcher);\n }\n matcher = escapeForRegexp(matcher).\n replace('\\\\*\\\\*', '.*').\n replace('\\\\*', '[^:/.?&;]*');\n return new RegExp('^' + matcher + '$');\n } else if (isRegExp(matcher)) {\n // The only other type of matcher allowed is a Regexp.\n // Match entire URL / disallow partial matches.\n // Flags are reset (i.e. no global, ignoreCase or multiline)\n return new RegExp('^' + matcher.source + '$');\n } else {\n throw $sceMinErr('imatcher',\n 'Matchers may only be \"self\", string patterns or RegExp objects');\n }\n}\n\n\nfunction adjustMatchers(matchers) {\n var adjustedMatchers = [];\n if (isDefined(matchers)) {\n forEach(matchers, function(matcher) {\n adjustedMatchers.push(adjustMatcher(matcher));\n });\n }\n return adjustedMatchers;\n}\n\n\n/**\n * @ngdoc service\n * @name $sceDelegate\n * @kind function\n *\n * @description\n *\n * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict\n * Contextual Escaping (SCE)} services to AngularJS.\n *\n * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of\n * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is\n * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to\n * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things\n * work because `$sce` delegates to `$sceDelegate` for these operations.\n *\n * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.\n *\n * The default instance of `$sceDelegate` should work out of the box with little pain. While you\n * can override it completely to change the behavior of `$sce`, the common case would\n * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting\n * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as\n * templates. Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist\n * $sceDelegateProvider.resourceUrlWhitelist} and {@link\n * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}\n */\n\n/**\n * @ngdoc provider\n * @name $sceDelegateProvider\n * @description\n *\n * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate\n * $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure\n * that the URLs used for sourcing Angular templates are safe. Refer {@link\n * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and\n * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}\n *\n * For the general details about this service in Angular, read the main page for {@link ng.$sce\n * Strict Contextual Escaping (SCE)}.\n *\n * **Example**: Consider the following case. \n *\n * - your app is hosted at url `http://myapp.example.com/`\n * - but some of your templates are hosted on other domains you control such as\n * `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.\n * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.\n *\n * Here is what a secure configuration for this scenario might look like:\n *\n * ```\n * angular.module('myApp', []).config(function($sceDelegateProvider) {\n * $sceDelegateProvider.resourceUrlWhitelist([\n * // Allow same origin resource loads.\n * 'self',\n * // Allow loading from our assets domain. Notice the difference between * and **.\n * 'http://srv*.assets.example.com/**'\n * ]);\n *\n * // The blacklist overrides the whitelist so the open redirect here is blocked.\n * $sceDelegateProvider.resourceUrlBlacklist([\n * 'http://myapp.example.com/clickThru**'\n * ]);\n * });\n * ```\n */\n\nfunction $SceDelegateProvider() {\n this.SCE_CONTEXTS = SCE_CONTEXTS;\n\n // Resource URLs can also be trusted by policy.\n var resourceUrlWhitelist = ['self'],\n resourceUrlBlacklist = [];\n\n /**\n * @ngdoc method\n * @name $sceDelegateProvider#resourceUrlWhitelist\n * @kind function\n *\n * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value\n * provided. This must be an array or null. A snapshot of this array is used so further\n * changes to the array are ignored.\n *\n * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n * allowed in this array.\n *\n * Note: **an empty whitelist array will block all URLs**!\n *\n * @return {Array} the currently set whitelist array.\n *\n * The **default value** when no whitelist has been explicitly set is `['self']` allowing only\n * same origin resource requests.\n *\n * @description\n * Sets/Gets the whitelist of trusted resource URLs.\n */\n this.resourceUrlWhitelist = function(value) {\n if (arguments.length) {\n resourceUrlWhitelist = adjustMatchers(value);\n }\n return resourceUrlWhitelist;\n };\n\n /**\n * @ngdoc method\n * @name $sceDelegateProvider#resourceUrlBlacklist\n * @kind function\n *\n * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value\n * provided. This must be an array or null. A snapshot of this array is used so further\n * changes to the array are ignored.\n *\n * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n * allowed in this array.\n *\n * The typical usage for the blacklist is to **block\n * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as\n * these would otherwise be trusted but actually return content from the redirected domain.\n *\n * Finally, **the blacklist overrides the whitelist** and has the final say.\n *\n * @return {Array} the currently set blacklist array.\n *\n * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there\n * is no blacklist.)\n *\n * @description\n * Sets/Gets the blacklist of trusted resource URLs.\n */\n\n this.resourceUrlBlacklist = function(value) {\n if (arguments.length) {\n resourceUrlBlacklist = adjustMatchers(value);\n }\n return resourceUrlBlacklist;\n };\n\n this.$get = ['$injector', function($injector) {\n\n var htmlSanitizer = function htmlSanitizer(html) {\n throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n };\n\n if ($injector.has('$sanitize')) {\n htmlSanitizer = $injector.get('$sanitize');\n }\n\n\n function matchUrl(matcher, parsedUrl) {\n if (matcher === 'self') {\n return urlIsSameOrigin(parsedUrl);\n } else {\n // definitely a regex. See adjustMatchers()\n return !!matcher.exec(parsedUrl.href);\n }\n }\n\n function isResourceUrlAllowedByPolicy(url) {\n var parsedUrl = urlResolve(url.toString());\n var i, n, allowed = false;\n // Ensure that at least one item from the whitelist allows this url.\n for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {\n if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {\n allowed = true;\n break;\n }\n }\n if (allowed) {\n // Ensure that no item from the blacklist blocked this url.\n for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {\n if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {\n allowed = false;\n break;\n }\n }\n }\n return allowed;\n }\n\n function generateHolderType(Base) {\n var holderType = function TrustedValueHolderType(trustedValue) {\n this.$$unwrapTrustedValue = function() {\n return trustedValue;\n };\n };\n if (Base) {\n holderType.prototype = new Base();\n }\n holderType.prototype.valueOf = function sceValueOf() {\n return this.$$unwrapTrustedValue();\n };\n holderType.prototype.toString = function sceToString() {\n return this.$$unwrapTrustedValue().toString();\n };\n return holderType;\n }\n\n var trustedValueHolderBase = generateHolderType(),\n byType = {};\n\n byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);\n byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);\n byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);\n byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);\n byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);\n\n /**\n * @ngdoc method\n * @name $sceDelegate#trustAs\n *\n * @description\n * Returns an object that is trusted by angular for use in specified strict\n * contextual escaping contexts (such as ng-bind-html, ng-include, any src\n * attribute interpolation, any dom event binding attribute interpolation\n * such as for onclick, etc.) that uses the provided value.\n * See {@link ng.$sce $sce} for enabling strict contextual escaping.\n *\n * @param {string} type The kind of context in which this value is safe for use. e.g. url,\n * resourceUrl, html, js and css.\n * @param {*} value The value that that should be considered trusted/safe.\n * @returns {*} A value that can be used to stand in for the provided `value` in places\n * where Angular expects a $sce.trustAs() return value.\n */\n function trustAs(type, trustedValue) {\n var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n if (!Constructor) {\n throw $sceMinErr('icontext',\n 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',\n type, trustedValue);\n }\n if (trustedValue === null || trustedValue === undefined || trustedValue === '') {\n return trustedValue;\n }\n // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting\n // mutable objects, we ensure here that the value passed in is actually a string.\n if (typeof trustedValue !== 'string') {\n throw $sceMinErr('itype',\n 'Attempted to trust a non-string value in a content requiring a string: Context: {0}',\n type);\n }\n return new Constructor(trustedValue);\n }\n\n /**\n * @ngdoc method\n * @name $sceDelegate#valueOf\n *\n * @description\n * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs\n * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link\n * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.\n *\n * If the passed parameter is not a value that had been returned by {@link\n * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.\n *\n * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}\n * call or anything else.\n * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs\n * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns\n * `value` unchanged.\n */\n function valueOf(maybeTrusted) {\n if (maybeTrusted instanceof trustedValueHolderBase) {\n return maybeTrusted.$$unwrapTrustedValue();\n } else {\n return maybeTrusted;\n }\n }\n\n /**\n * @ngdoc method\n * @name $sceDelegate#getTrusted\n *\n * @description\n * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and\n * returns the originally supplied value if the queried context type is a supertype of the\n * created type. If this condition isn't satisfied, throws an exception.\n *\n * @param {string} type The kind of context in which this value is to be used.\n * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs\n * `$sceDelegate.trustAs`} call.\n * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs\n * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception.\n */\n function getTrusted(type, maybeTrusted) {\n if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') {\n return maybeTrusted;\n }\n var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n if (constructor && maybeTrusted instanceof constructor) {\n return maybeTrusted.$$unwrapTrustedValue();\n }\n // If we get here, then we may only take one of two actions.\n // 1. sanitize the value for the requested type, or\n // 2. throw an exception.\n if (type === SCE_CONTEXTS.RESOURCE_URL) {\n if (isResourceUrlAllowedByPolicy(maybeTrusted)) {\n return maybeTrusted;\n } else {\n throw $sceMinErr('insecurl',\n 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}',\n maybeTrusted.toString());\n }\n } else if (type === SCE_CONTEXTS.HTML) {\n return htmlSanitizer(maybeTrusted);\n }\n throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n }\n\n return { trustAs: trustAs,\n getTrusted: getTrusted,\n valueOf: valueOf };\n }];\n}\n\n\n/**\n * @ngdoc provider\n * @name $sceProvider\n * @description\n *\n * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.\n * - enable/disable Strict Contextual Escaping (SCE) in a module\n * - override the default implementation with a custom delegate\n *\n * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.\n */\n\n/* jshint maxlen: false*/\n\n/**\n * @ngdoc service\n * @name $sce\n * @kind function\n *\n * @description\n *\n * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.\n *\n * # Strict Contextual Escaping\n *\n * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain\n * contexts to result in a value that is marked as safe to use for that context. One example of\n * such a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer\n * to these contexts as privileged or SCE contexts.\n *\n * As of version 1.2, Angular ships with SCE enabled by default.\n *\n * Note: When enabled (the default), IE<11 in quirks mode is not supported. In this mode, IE<11 allow\n * one to execute arbitrary javascript by the use of the expression() syntax. Refer\n * to learn more about them.\n * You can ensure your document is in standards mode and not quirks mode by adding ``\n * to the top of your HTML document.\n *\n * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for\n * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.\n *\n * Here's an example of a binding in a privileged context:\n *\n * ```\n * \n *
\n * ```\n *\n * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE\n * disabled, this application allows the user to render arbitrary HTML into the DIV.\n * In a more realistic example, one may be rendering user comments, blog articles, etc. via\n * bindings. (HTML is just one example of a context where rendering user controlled input creates\n * security vulnerabilities.)\n *\n * For the case of HTML, you might use a library, either on the client side, or on the server side,\n * to sanitize unsafe HTML before binding to the value and rendering it in the document.\n *\n * How would you ensure that every place that used these types of bindings was bound to a value that\n * was sanitized by your library (or returned as safe for rendering by your server?) How can you\n * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some\n * properties/fields and forgot to update the binding to the sanitized value?\n *\n * To be secure by default, you want to ensure that any such bindings are disallowed unless you can\n * determine that something explicitly says it's safe to use a value for binding in that\n * context. You can then audit your code (a simple grep would do) to ensure that this is only done\n * for those values that you can easily tell are safe - because they were received from your server,\n * sanitized by your library, etc. You can organize your codebase to help with this - perhaps\n * allowing only the files in a specific directory to do this. Ensuring that the internal API\n * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.\n *\n * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}\n * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to\n * obtain values that will be accepted by SCE / privileged contexts.\n *\n *\n * ## How does it work?\n *\n * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted\n * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link\n * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the\n * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.\n *\n * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link\n * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly\n * simplified):\n *\n * ```\n * var ngBindHtmlDirective = ['$sce', function($sce) {\n * return function(scope, element, attr) {\n * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {\n * element.html(value || '');\n * });\n * };\n * }];\n * ```\n *\n * ## Impact on loading templates\n *\n * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as\n * `templateUrl`'s specified by {@link guide/directive directives}.\n *\n * By default, Angular only loads templates from the same domain and protocol as the application\n * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl\n * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or\n * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist\n * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.\n *\n * *Please note*:\n * The browser's\n * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)\n * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)\n * policy apply in addition to this and may further restrict whether the template is successfully\n * loaded. This means that without the right CORS policy, loading templates from a different domain\n * won't work on all browsers. Also, loading templates from `file://` URL does not work on some\n * browsers.\n *\n * ## This feels like too much overhead\n *\n * It's important to remember that SCE only applies to interpolation expressions.\n *\n * If your expressions are constant literals, they're automatically trusted and you don't need to\n * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.\n * `
implicitly trusted'\">
`) just works.\n *\n * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them\n * through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here.\n *\n * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load\n * templates in `ng-include` from your application's domain without having to even know about SCE.\n * It blocks loading templates from other domains or loading templates over http from an https\n * served document. You can change these by setting your own custom {@link\n * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link\n * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.\n *\n * This significantly reduces the overhead. It is far easier to pay the small overhead and have an\n * application that's secure and can be audited to verify that with much more ease than bolting\n * security onto an application later.\n *\n * \n * ## What trusted context types are supported?\n *\n * | Context | Notes |\n * |---------------------|----------------|\n * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |\n * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |\n * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`
Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |\n * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. |\n *\n * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist}
\n *\n * Each element in these arrays must be one of the following:\n *\n * - **'self'**\n * - The special **string**, `'self'`, can be used to match against all URLs of the **same\n * domain** as the application document using the **same protocol**.\n * - **String** (except the special value `'self'`)\n * - The string is matched against the full *normalized / absolute URL* of the resource\n * being tested (substring matches are not good enough.)\n * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters\n * match themselves.\n * - `*`: matches zero or more occurrences of any character other than one of the following 6\n * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'. It's a useful wildcard for use\n * in a whitelist.\n * - `**`: matches zero or more occurrences of *any* character. As such, it's not\n * not appropriate to use in for a scheme, domain, etc. as it would match too much. (e.g.\n * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might\n * not have been the intention.) Its usage at the very end of the path is ok. (e.g.\n * http://foo.example.com/templates/**).\n * - **RegExp** (*see caveat below*)\n * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax\n * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to\n * accidentally introduce a bug when one updates a complex expression (imho, all regexes should\n * have good test coverage.). For instance, the use of `.` in the regex is correct only in a\n * small number of cases. A `.` character in the regex used when matching the scheme or a\n * subdomain could be matched against a `:` or literal `.` that was likely not intended. It\n * is highly recommended to use the string patterns and only fall back to regular expressions\n * if they as a last resort.\n * - The regular expression must be an instance of RegExp (i.e. not a string.) It is\n * matched against the **entire** *normalized / absolute URL* of the resource being tested\n * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags\n * present on the RegExp (such as multiline, global, ignoreCase) are ignored.\n * - If you are generating your JavaScript from some other templating engine (not\n * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),\n * remember to escape your regular expression (and be aware that you might need more than\n * one level of escaping depending on your templating engine and the way you interpolated\n * the value.) Do make use of your platform's escaping mechanism as it might be good\n * enough before coding your own. e.g. Ruby has\n * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)\n * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).\n * Javascript lacks a similar built in function for escaping. Take a look at Google\n * Closure library's [goog.string.regExpEscape(s)](\n * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).\n *\n * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.\n *\n * ## Show me an example using SCE.\n *\n * \n * \n *
\n *

\n * User comments
\n * By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when\n * $sanitize is available. If $sanitize isn't available, this results in an error instead of an\n * exploit.\n *
\n *
\n * {{userComment.name}}:\n * \n *
\n *
\n *
\n *
\n *
\n *\n * \n * angular.module('mySceApp', ['ngSanitize'])\n * .controller('AppController', ['$http', '$templateCache', '$sce',\n * function($http, $templateCache, $sce) {\n * var self = this;\n * $http.get(\"test_data.json\", {cache: $templateCache}).success(function(userComments) {\n * self.userComments = userComments;\n * });\n * self.explicitlyTrustedHtml = $sce.trustAsHtml(\n * 'Hover over this text.');\n * }]);\n * \n *\n * \n * [\n * { \"name\": \"Alice\",\n * \"htmlComment\":\n * \"Is anyone reading this?\"\n * },\n * { \"name\": \"Bob\",\n * \"htmlComment\": \"Yes! Am I the only other one?\"\n * }\n * ]\n * \n *\n * \n * describe('SCE doc demo', function() {\n * it('should sanitize untrusted values', function() {\n * expect(element.all(by.css('.htmlComment')).first().getInnerHtml())\n * .toBe('Is anyone reading this?');\n * });\n *\n * it('should NOT sanitize explicitly trusted values', function() {\n * expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(\n * 'Hover over this text.');\n * });\n * });\n * \n *
\n *\n *\n *\n * ## Can I disable SCE completely?\n *\n * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits\n * for little coding overhead. It will be much harder to take an SCE disabled application and\n * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE\n * for cases where you have a lot of existing code that was written before SCE was introduced and\n * you're migrating them a module at a time.\n *\n * That said, here's how you can completely disable SCE:\n *\n * ```\n * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {\n * // Completely disable SCE. For demonstration purposes only!\n * // Do not use in new projects.\n * $sceProvider.enabled(false);\n * });\n * ```\n *\n */\n/* jshint maxlen: 100 */\n\nfunction $SceProvider() {\n var enabled = true;\n\n /**\n * @ngdoc method\n * @name $sceProvider#enabled\n * @kind function\n *\n * @param {boolean=} value If provided, then enables/disables SCE.\n * @return {boolean} true if SCE is enabled, false otherwise.\n *\n * @description\n * Enables/disables SCE and returns the current value.\n */\n this.enabled = function(value) {\n if (arguments.length) {\n enabled = !!value;\n }\n return enabled;\n };\n\n\n /* Design notes on the default implementation for SCE.\n *\n * The API contract for the SCE delegate\n * -------------------------------------\n * The SCE delegate object must provide the following 3 methods:\n *\n * - trustAs(contextEnum, value)\n * This method is used to tell the SCE service that the provided value is OK to use in the\n * contexts specified by contextEnum. It must return an object that will be accepted by\n * getTrusted() for a compatible contextEnum and return this value.\n *\n * - valueOf(value)\n * For values that were not produced by trustAs(), return them as is. For values that were\n * produced by trustAs(), return the corresponding input value to trustAs. Basically, if\n * trustAs is wrapping the given values into some type, this operation unwraps it when given\n * such a value.\n *\n * - getTrusted(contextEnum, value)\n * This function should return the a value that is safe to use in the context specified by\n * contextEnum or throw and exception otherwise.\n *\n * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be\n * opaque or wrapped in some holder object. That happens to be an implementation detail. For\n * instance, an implementation could maintain a registry of all trusted objects by context. In\n * such a case, trustAs() would return the same object that was passed in. getTrusted() would\n * return the same object passed in if it was found in the registry under a compatible context or\n * throw an exception otherwise. An implementation might only wrap values some of the time based\n * on some criteria. getTrusted() might return a value and not throw an exception for special\n * constants or objects even if not wrapped. All such implementations fulfill this contract.\n *\n *\n * A note on the inheritance model for SCE contexts\n * ------------------------------------------------\n * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This\n * is purely an implementation details.\n *\n * The contract is simply this:\n *\n * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)\n * will also succeed.\n *\n * Inheritance happens to capture this in a natural way. In some future, we\n * may not use inheritance anymore. That is OK because no code outside of\n * sce.js and sceSpecs.js would need to be aware of this detail.\n */\n\n this.$get = ['$parse', '$sceDelegate', function(\n $parse, $sceDelegate) {\n // Prereq: Ensure that we're not running in IE<11 quirks mode. In that mode, IE < 11 allow\n // the \"expression(javascript expression)\" syntax which is insecure.\n if (enabled && msie < 8) {\n throw $sceMinErr('iequirks',\n 'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' +\n 'mode. You can fix this by adding the text to the top of your HTML ' +\n 'document. See http://docs.angularjs.org/api/ng.$sce for more information.');\n }\n\n var sce = shallowCopy(SCE_CONTEXTS);\n\n /**\n * @ngdoc method\n * @name $sce#isEnabled\n * @kind function\n *\n * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you\n * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.\n *\n * @description\n * Returns a boolean indicating if SCE is enabled.\n */\n sce.isEnabled = function() {\n return enabled;\n };\n sce.trustAs = $sceDelegate.trustAs;\n sce.getTrusted = $sceDelegate.getTrusted;\n sce.valueOf = $sceDelegate.valueOf;\n\n if (!enabled) {\n sce.trustAs = sce.getTrusted = function(type, value) { return value; };\n sce.valueOf = identity;\n }\n\n /**\n * @ngdoc method\n * @name $sce#parseAs\n *\n * @description\n * Converts Angular {@link guide/expression expression} into a function. This is like {@link\n * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it\n * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,\n * *result*)}\n *\n * @param {string} type The kind of SCE context in which this result will be used.\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n * * `context` – `{object}` – an object against which any expressions embedded in the strings\n * are evaluated against (typically a scope object).\n * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n * `context`.\n */\n sce.parseAs = function sceParseAs(type, expr) {\n var parsed = $parse(expr);\n if (parsed.literal && parsed.constant) {\n return parsed;\n } else {\n return $parse(expr, function(value) {\n return sce.getTrusted(type, value);\n });\n }\n };\n\n /**\n * @ngdoc method\n * @name $sce#trustAs\n *\n * @description\n * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such,\n * returns an object that is trusted by angular for use in specified strict contextual\n * escaping contexts (such as ng-bind-html, ng-include, any src attribute\n * interpolation, any dom event binding attribute interpolation such as for onclick, etc.)\n * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual\n * escaping.\n *\n * @param {string} type The kind of context in which this value is safe for use. e.g. url,\n * resource_url, html, js and css.\n * @param {*} value The value that that should be considered trusted/safe.\n * @returns {*} A value that can be used to stand in for the provided `value` in places\n * where Angular expects a $sce.trustAs() return value.\n */\n\n /**\n * @ngdoc method\n * @name $sce#trustAsHtml\n *\n * @description\n * Shorthand method. `$sce.trustAsHtml(value)` →\n * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}\n *\n * @param {*} value The value to trustAs.\n * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml\n * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives\n * only accept expressions that are either literal constants or are the\n * return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n */\n\n /**\n * @ngdoc method\n * @name $sce#trustAsUrl\n *\n * @description\n * Shorthand method. `$sce.trustAsUrl(value)` →\n * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}\n *\n * @param {*} value The value to trustAs.\n * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl\n * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives\n * only accept expressions that are either literal constants or are the\n * return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n */\n\n /**\n * @ngdoc method\n * @name $sce#trustAsResourceUrl\n *\n * @description\n * Shorthand method. `$sce.trustAsResourceUrl(value)` →\n * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}\n *\n * @param {*} value The value to trustAs.\n * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl\n * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives\n * only accept expressions that are either literal constants or are the return\n * value of {@link ng.$sce#trustAs $sce.trustAs}.)\n */\n\n /**\n * @ngdoc method\n * @name $sce#trustAsJs\n *\n * @description\n * Shorthand method. `$sce.trustAsJs(value)` →\n * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}\n *\n * @param {*} value The value to trustAs.\n * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs\n * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives\n * only accept expressions that are either literal constants or are the\n * return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n */\n\n /**\n * @ngdoc method\n * @name $sce#getTrusted\n *\n * @description\n * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such,\n * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the\n * originally supplied value if the queried context type is a supertype of the created type.\n * If this condition isn't satisfied, throws an exception.\n *\n * @param {string} type The kind of context in which this value is to be used.\n * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}\n * call.\n * @returns {*} The value the was originally provided to\n * {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.\n * Otherwise, throws an exception.\n */\n\n /**\n * @ngdoc method\n * @name $sce#getTrustedHtml\n *\n * @description\n * Shorthand method. `$sce.getTrustedHtml(value)` →\n * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}\n *\n * @param {*} value The value to pass to `$sce.getTrusted`.\n * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`\n */\n\n /**\n * @ngdoc method\n * @name $sce#getTrustedCss\n *\n * @description\n * Shorthand method. `$sce.getTrustedCss(value)` →\n * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}\n *\n * @param {*} value The value to pass to `$sce.getTrusted`.\n * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`\n */\n\n /**\n * @ngdoc method\n * @name $sce#getTrustedUrl\n *\n * @description\n * Shorthand method. `$sce.getTrustedUrl(value)` →\n * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}\n *\n * @param {*} value The value to pass to `$sce.getTrusted`.\n * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`\n */\n\n /**\n * @ngdoc method\n * @name $sce#getTrustedResourceUrl\n *\n * @description\n * Shorthand method. `$sce.getTrustedResourceUrl(value)` →\n * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}\n *\n * @param {*} value The value to pass to `$sceDelegate.getTrusted`.\n * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`\n */\n\n /**\n * @ngdoc method\n * @name $sce#getTrustedJs\n *\n * @description\n * Shorthand method. `$sce.getTrustedJs(value)` →\n * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}\n *\n * @param {*} value The value to pass to `$sce.getTrusted`.\n * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`\n */\n\n /**\n * @ngdoc method\n * @name $sce#parseAsHtml\n *\n * @description\n * Shorthand method. `$sce.parseAsHtml(expression string)` →\n * {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`}\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n * * `context` – `{object}` – an object against which any expressions embedded in the strings\n * are evaluated against (typically a scope object).\n * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n * `context`.\n */\n\n /**\n * @ngdoc method\n * @name $sce#parseAsCss\n *\n * @description\n * Shorthand method. `$sce.parseAsCss(value)` →\n * {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`}\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n * * `context` – `{object}` – an object against which any expressions embedded in the strings\n * are evaluated against (typically a scope object).\n * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n * `context`.\n */\n\n /**\n * @ngdoc method\n * @name $sce#parseAsUrl\n *\n * @description\n * Shorthand method. `$sce.parseAsUrl(value)` →\n * {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`}\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n * * `context` – `{object}` – an object against which any expressions embedded in the strings\n * are evaluated against (typically a scope object).\n * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n * `context`.\n */\n\n /**\n * @ngdoc method\n * @name $sce#parseAsResourceUrl\n *\n * @description\n * Shorthand method. `$sce.parseAsResourceUrl(value)` →\n * {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`}\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n * * `context` – `{object}` – an object against which any expressions embedded in the strings\n * are evaluated against (typically a scope object).\n * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n * `context`.\n */\n\n /**\n * @ngdoc method\n * @name $sce#parseAsJs\n *\n * @description\n * Shorthand method. `$sce.parseAsJs(value)` →\n * {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`}\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n * * `context` – `{object}` – an object against which any expressions embedded in the strings\n * are evaluated against (typically a scope object).\n * * `locals` – `{object=}` – local variables context object, useful for overriding values in\n * `context`.\n */\n\n // Shorthand delegations.\n var parse = sce.parseAs,\n getTrusted = sce.getTrusted,\n trustAs = sce.trustAs;\n\n forEach(SCE_CONTEXTS, function(enumValue, name) {\n var lName = lowercase(name);\n sce[camelCase(\"parse_as_\" + lName)] = function(expr) {\n return parse(enumValue, expr);\n };\n sce[camelCase(\"get_trusted_\" + lName)] = function(value) {\n return getTrusted(enumValue, value);\n };\n sce[camelCase(\"trust_as_\" + lName)] = function(value) {\n return trustAs(enumValue, value);\n };\n });\n\n return sce;\n }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name $sniffer\n * @requires $window\n * @requires $document\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} transitions Does the browser support CSS transition events ?\n * @property {boolean} animations Does the browser support CSS animation events ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n this.$get = ['$window', '$document', function($window, $document) {\n var eventSupport = {},\n android =\n int((/android (\\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),\n boxee = /Boxee/i.test(($window.navigator || {}).userAgent),\n document = $document[0] || {},\n vendorPrefix,\n vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/,\n bodyStyle = document.body && document.body.style,\n transitions = false,\n animations = false,\n match;\n\n if (bodyStyle) {\n for (var prop in bodyStyle) {\n if (match = vendorRegex.exec(prop)) {\n vendorPrefix = match[0];\n vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);\n break;\n }\n }\n\n if (!vendorPrefix) {\n vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';\n }\n\n transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));\n animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));\n\n if (android && (!transitions || !animations)) {\n transitions = isString(document.body.style.webkitTransition);\n animations = isString(document.body.style.webkitAnimation);\n }\n }\n\n\n return {\n // Android has history.pushState, but it does not update location correctly\n // so let's not use the history API at all.\n // http://code.google.com/p/android/issues/detail?id=17471\n // https://github.com/angular/angular.js/issues/904\n\n // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has\n // so let's not use the history API also\n // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined\n // jshint -W018\n history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),\n // jshint +W018\n hasEvent: function(event) {\n // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n // it. In particular the event is not fired when backspace or delete key are pressed or\n // when cut operation is performed.\n // IE10+ implements 'input' event but it erroneously fires under various situations,\n // e.g. when placeholder changes, or a form is focused.\n if (event === 'input' && msie <= 11) return false;\n\n if (isUndefined(eventSupport[event])) {\n var divElm = document.createElement('div');\n eventSupport[event] = 'on' + event in divElm;\n }\n\n return eventSupport[event];\n },\n csp: csp(),\n vendorPrefix: vendorPrefix,\n transitions: transitions,\n animations: animations,\n android: android\n };\n }];\n}\n\nvar $compileMinErr = minErr('$compile');\n\n/**\n * @ngdoc service\n * @name $templateRequest\n *\n * @description\n * The `$templateRequest` service downloads the provided template using `$http` and, upon success,\n * stores the contents inside of `$templateCache`. If the HTTP request fails or the response data\n * of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted\n * by setting the 2nd parameter of the function to true).\n *\n * @param {string} tpl The HTTP request template URL\n * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty\n *\n * @return {Promise} the HTTP Promise for the given.\n *\n * @property {number} totalPendingRequests total amount of pending template requests being downloaded.\n */\nfunction $TemplateRequestProvider() {\n this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) {\n function handleRequestFn(tpl, ignoreRequestError) {\n handleRequestFn.totalPendingRequests++;\n\n var transformResponse = $http.defaults && $http.defaults.transformResponse;\n\n if (isArray(transformResponse)) {\n transformResponse = transformResponse.filter(function(transformer) {\n return transformer !== defaultHttpResponseTransform;\n });\n } else if (transformResponse === defaultHttpResponseTransform) {\n transformResponse = null;\n }\n\n var httpOptions = {\n cache: $templateCache,\n transformResponse: transformResponse\n };\n\n return $http.get(tpl, httpOptions)\n .finally(function() {\n handleRequestFn.totalPendingRequests--;\n })\n .then(function(response) {\n return response.data;\n }, handleError);\n\n function handleError(resp) {\n if (!ignoreRequestError) {\n throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl);\n }\n return $q.reject(resp);\n }\n }\n\n handleRequestFn.totalPendingRequests = 0;\n\n return handleRequestFn;\n }];\n}\n\nfunction $$TestabilityProvider() {\n this.$get = ['$rootScope', '$browser', '$location',\n function($rootScope, $browser, $location) {\n\n /**\n * @name $testability\n *\n * @description\n * The private $$testability service provides a collection of methods for use when debugging\n * or by automated test and debugging tools.\n */\n var testability = {};\n\n /**\n * @name $$testability#findBindings\n *\n * @description\n * Returns an array of elements that are bound (via ng-bind or {{}})\n * to expressions matching the input.\n *\n * @param {Element} element The element root to search from.\n * @param {string} expression The binding expression to match.\n * @param {boolean} opt_exactMatch If true, only returns exact matches\n * for the expression. Filters and whitespace are ignored.\n */\n testability.findBindings = function(element, expression, opt_exactMatch) {\n var bindings = element.getElementsByClassName('ng-binding');\n var matches = [];\n forEach(bindings, function(binding) {\n var dataBinding = angular.element(binding).data('$binding');\n if (dataBinding) {\n forEach(dataBinding, function(bindingName) {\n if (opt_exactMatch) {\n var matcher = new RegExp('(^|\\\\s)' + escapeForRegexp(expression) + '(\\\\s|\\\\||$)');\n if (matcher.test(bindingName)) {\n matches.push(binding);\n }\n } else {\n if (bindingName.indexOf(expression) != -1) {\n matches.push(binding);\n }\n }\n });\n }\n });\n return matches;\n };\n\n /**\n * @name $$testability#findModels\n *\n * @description\n * Returns an array of elements that are two-way found via ng-model to\n * expressions matching the input.\n *\n * @param {Element} element The element root to search from.\n * @param {string} expression The model expression to match.\n * @param {boolean} opt_exactMatch If true, only returns exact matches\n * for the expression.\n */\n testability.findModels = function(element, expression, opt_exactMatch) {\n var prefixes = ['ng-', 'data-ng-', 'ng\\\\:'];\n for (var p = 0; p < prefixes.length; ++p) {\n var attributeEquals = opt_exactMatch ? '=' : '*=';\n var selector = '[' + prefixes[p] + 'model' + attributeEquals + '\"' + expression + '\"]';\n var elements = element.querySelectorAll(selector);\n if (elements.length) {\n return elements;\n }\n }\n };\n\n /**\n * @name $$testability#getLocation\n *\n * @description\n * Shortcut for getting the location in a browser agnostic way. Returns\n * the path, search, and hash. (e.g. /path?a=b#hash)\n */\n testability.getLocation = function() {\n return $location.url();\n };\n\n /**\n * @name $$testability#setLocation\n *\n * @description\n * Shortcut for navigating to a location without doing a full page reload.\n *\n * @param {string} url The location url (path, search and hash,\n * e.g. /path?a=b#hash) to go to.\n */\n testability.setLocation = function(url) {\n if (url !== $location.url()) {\n $location.url(url);\n $rootScope.$digest();\n }\n };\n\n /**\n * @name $$testability#whenStable\n *\n * @description\n * Calls the callback when $timeout and $http requests are completed.\n *\n * @param {function} callback\n */\n testability.whenStable = function(callback) {\n $browser.notifyWhenNoOutstandingRequests(callback);\n };\n\n return testability;\n }];\n}\n\nfunction $TimeoutProvider() {\n this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',\n function($rootScope, $browser, $q, $$q, $exceptionHandler) {\n var deferreds = {};\n\n\n /**\n * @ngdoc service\n * @name $timeout\n *\n * @description\n * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n * block and delegates any exceptions to\n * {@link ng.$exceptionHandler $exceptionHandler} service.\n *\n * The return value of registering a timeout function is a promise, which will be resolved when\n * the timeout is reached and the timeout function is executed.\n *\n * To cancel a timeout request, call `$timeout.cancel(promise)`.\n *\n * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n * synchronously flush the queue of deferred functions.\n *\n * @param {function()} fn A function, whose execution should be delayed.\n * @param {number=} [delay=0] Delay in milliseconds.\n * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise\n * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n * promise will be resolved with is the return value of the `fn` function.\n *\n */\n function timeout(fn, delay, invokeApply) {\n var skipApply = (isDefined(invokeApply) && !invokeApply),\n deferred = (skipApply ? $$q : $q).defer(),\n promise = deferred.promise,\n timeoutId;\n\n timeoutId = $browser.defer(function() {\n try {\n deferred.resolve(fn());\n } catch (e) {\n deferred.reject(e);\n $exceptionHandler(e);\n }\n finally {\n delete deferreds[promise.$$timeoutId];\n }\n\n if (!skipApply) $rootScope.$apply();\n }, delay);\n\n promise.$$timeoutId = timeoutId;\n deferreds[timeoutId] = deferred;\n\n return promise;\n }\n\n\n /**\n * @ngdoc method\n * @name $timeout#cancel\n *\n * @description\n * Cancels a task associated with the `promise`. As a result of this, the promise will be\n * resolved with a rejection.\n *\n * @param {Promise=} promise Promise returned by the `$timeout` function.\n * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n * canceled.\n */\n timeout.cancel = function(promise) {\n if (promise && promise.$$timeoutId in deferreds) {\n deferreds[promise.$$timeoutId].reject('canceled');\n delete deferreds[promise.$$timeoutId];\n return $browser.defer.cancel(promise.$$timeoutId);\n }\n return false;\n };\n\n return timeout;\n }];\n}\n\n// NOTE: The usage of window and document instead of $window and $document here is\n// deliberate. This service depends on the specific behavior of anchor nodes created by the\n// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and\n// cause us to break tests. In addition, when the browser resolves a URL for XHR, it\n// doesn't know about mocked locations and resolves URLs to the real document - which is\n// exactly the behavior needed here. There is little value is mocking these out for this\n// service.\nvar urlParsingNode = document.createElement(\"a\");\nvar originUrl = urlResolve(window.location.href);\n\n\n/**\n *\n * Implementation Notes for non-IE browsers\n * ----------------------------------------\n * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,\n * results both in the normalizing and parsing of the URL. Normalizing means that a relative\n * URL will be resolved into an absolute URL in the context of the application document.\n * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related\n * properties are all populated to reflect the normalized URL. This approach has wide\n * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See\n * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n *\n * Implementation Notes for IE\n * ---------------------------\n * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other\n * browsers. However, the parsed components will not be set if the URL assigned did not specify\n * them. (e.g. if you assign a.href = \"foo\", then a.protocol, a.host, etc. will be empty.) We\n * work around that by performing the parsing in a 2nd step by taking a previously normalized\n * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the\n * properties such as protocol, hostname, port, etc.\n *\n * IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one\n * uses the inner HTML approach to assign the URL as part of an HTML snippet -\n * http://stackoverflow.com/a/472729) However, setting img[src] does normalize the URL.\n * Unfortunately, setting img[src] to something like \"javascript:foo\" on IE throws an exception.\n * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that\n * method and IE < 8 is unsupported.\n *\n * References:\n * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement\n * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n * http://url.spec.whatwg.org/#urlutils\n * https://github.com/angular/angular.js/pull/2902\n * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/\n *\n * @kind function\n * @param {string} url The URL to be parsed.\n * @description Normalizes and parses a URL.\n * @returns {object} Returns the normalized URL as a dictionary.\n *\n * | member name | Description |\n * |---------------|----------------|\n * | href | A normalized version of the provided URL if it was not an absolute URL |\n * | protocol | The protocol including the trailing colon |\n * | host | The host and port (if the port is non-default) of the normalizedUrl |\n * | search | The search params, minus the question mark |\n * | hash | The hash string, minus the hash symbol\n * | hostname | The hostname\n * | port | The port, without \":\"\n * | pathname | The pathname, beginning with \"/\"\n *\n */\nfunction urlResolve(url) {\n var href = url;\n\n if (msie) {\n // Normalize before parse. Refer Implementation Notes on why this is\n // done in two steps on IE.\n urlParsingNode.setAttribute(\"href\", href);\n href = urlParsingNode.href;\n }\n\n urlParsingNode.setAttribute('href', href);\n\n // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils\n return {\n href: urlParsingNode.href,\n protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',\n host: urlParsingNode.host,\n search: urlParsingNode.search ? urlParsingNode.search.replace(/^\\?/, '') : '',\n hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',\n hostname: urlParsingNode.hostname,\n port: urlParsingNode.port,\n pathname: (urlParsingNode.pathname.charAt(0) === '/')\n ? urlParsingNode.pathname\n : '/' + urlParsingNode.pathname\n };\n}\n\n/**\n * Parse a request URL and determine whether this is a same-origin request as the application document.\n *\n * @param {string|object} requestUrl The url of the request as a string that will be resolved\n * or a parsed URL object.\n * @returns {boolean} Whether the request is for the same origin as the application document.\n */\nfunction urlIsSameOrigin(requestUrl) {\n var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;\n return (parsed.protocol === originUrl.protocol &&\n parsed.host === originUrl.host);\n}\n\n/**\n * @ngdoc service\n * @name $window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overridden, removed or mocked for testing.\n *\n * Expressions, like the one defined for the `ngClick` directive in the example\n * below, are evaluated with respect to the current scope. Therefore, there is\n * no risk of inadvertently coding in a dependency on a global value in such an\n * expression.\n *\n * @example\n \n \n \n
\n \n \n
\n
\n \n it('should display the greeting in the input box', function() {\n element(by.model('greeting')).sendKeys('Hello, E2E Tests');\n // If we click the button it will block the test runner\n // element(':button').click();\n });\n \n
\n */\nfunction $WindowProvider() {\n this.$get = valueFn(window);\n}\n\n/* global currencyFilter: true,\n dateFilter: true,\n filterFilter: true,\n jsonFilter: true,\n limitToFilter: true,\n lowercaseFilter: true,\n numberFilter: true,\n orderByFilter: true,\n uppercaseFilter: true,\n */\n\n/**\n * @ngdoc provider\n * @name $filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be\n * Dependency Injected. To achieve this a filter definition consists of a factory function which is\n * annotated with dependencies and is responsible for creating a filter function.\n *\n * ```js\n * // Filter registration\n * function MyModule($provide, $filterProvider) {\n * // create a service to demonstrate injection (not always needed)\n * $provide.value('greet', function(name){\n * return 'Hello ' + name + '!';\n * });\n *\n * // register a filter factory which uses the\n * // greet service to demonstrate DI.\n * $filterProvider.register('greet', function(greet){\n * // return the filter function which uses the greet service\n * // to generate salutation\n * return function(text) {\n * // filters need to be forgiving so check input validity\n * return text && greet(text) || text;\n * };\n * });\n * }\n * ```\n *\n * The filter function is registered with the `$injector` under the filter name suffix with\n * `Filter`.\n *\n * ```js\n * it('should be the same instance', inject(\n * function($filterProvider) {\n * $filterProvider.register('reverse', function(){\n * return ...;\n * });\n * },\n * function($filter, reverseFilter) {\n * expect($filter('reverse')).toBe(reverseFilter);\n * });\n * ```\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/filter Filters} in the Angular Developer Guide.\n */\n\n/**\n * @ngdoc service\n * @name $filter\n * @kind function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n * {{ expression [| filter_name[:parameter_value] ... ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n * @example\n \n \n
\n

{{ originalText }}

\n

{{ filteredText }}

\n
\n
\n\n \n angular.module('filterExample', [])\n .controller('MainCtrl', function($scope, $filter) {\n $scope.originalText = 'hello';\n $scope.filteredText = $filter('uppercase')($scope.originalText);\n });\n \n
\n */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n var suffix = 'Filter';\n\n /**\n * @ngdoc method\n * @name $filterProvider#register\n * @param {string|Object} name Name of the filter function, or an object map of filters where\n * the keys are the filter names and the values are the filter factories.\n * @returns {Object} Registered filter instance, or if a map of filters was provided then a map\n * of the registered filter instances.\n */\n function register(name, factory) {\n if (isObject(name)) {\n var filters = {};\n forEach(name, function(filter, key) {\n filters[key] = register(key, filter);\n });\n return filters;\n } else {\n return $provide.factory(name + suffix, factory);\n }\n }\n this.register = register;\n\n this.$get = ['$injector', function($injector) {\n return function(name) {\n return $injector.get(name + suffix);\n };\n }];\n\n ////////////////////////////////////////\n\n /* global\n currencyFilter: false,\n dateFilter: false,\n filterFilter: false,\n jsonFilter: false,\n limitToFilter: false,\n lowercaseFilter: false,\n numberFilter: false,\n orderByFilter: false,\n uppercaseFilter: false,\n */\n\n register('currency', currencyFilter);\n register('date', dateFilter);\n register('filter', filterFilter);\n register('json', jsonFilter);\n register('limitTo', limitToFilter);\n register('lowercase', lowercaseFilter);\n register('number', numberFilter);\n register('orderBy', orderByFilter);\n register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name filter\n * @kind function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n * `array`.\n *\n * Can be one of:\n *\n * - `string`: The string is used for matching against the contents of the `array`. All strings or\n * objects with string properties in `array` that match this string will be returned. This also\n * applies to nested object properties.\n * The predicate can be negated by prefixing the string with `!`.\n *\n * - `Object`: A pattern object can be used to filter specific properties on objects contained\n * by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n * which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n * property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n * property of the object or its nested object properties. That's equivalent to the simple\n * substring match with a `string` as described above. The predicate can be negated by prefixing\n * the string with `!`.\n * For example `{name: \"!M\"}` predicate will return an array of items which have property `name`\n * not containing \"M\".\n *\n * Note that a named property will match properties on the same level only, while the special\n * `$` property will match properties on the same level or deeper. E.g. an array item like\n * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but\n * **will** be matched by `{$: 'John'}`.\n *\n * - `function(value, index)`: A predicate function can be used to write arbitrary filters. The\n * function is called for each element of `array`. The final result is an array of those\n * elements that the predicate returned true for.\n *\n * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in\n * determining if the expected value (from the filter expression) and actual value (from\n * the object in the array) should be considered a match.\n *\n * Can be one of:\n *\n * - `function(actual, expected)`:\n * The function will be given the object value and the predicate value to compare and\n * should return true if both values should be considered equal.\n *\n * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.\n * This is essentially strict comparison of expected and actual.\n *\n * - `false|undefined`: A short hand for a function which will look for a substring match in case\n * insensitive way.\n *\n * @example\n \n \n
\n\n Search: \n \n \n \n \n \n \n
NamePhone
{{friend.name}}{{friend.phone}}
\n
\n Any:
\n Name only
\n Phone only
\n Equality
\n \n \n \n \n \n \n
NamePhone
{{friendObj.name}}{{friendObj.phone}}
\n
\n \n var expectFriendNames = function(expectedNames, key) {\n element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {\n arr.forEach(function(wd, i) {\n expect(wd.getText()).toMatch(expectedNames[i]);\n });\n });\n };\n\n it('should search across all fields when filtering with a string', function() {\n var searchText = element(by.model('searchText'));\n searchText.clear();\n searchText.sendKeys('m');\n expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');\n\n searchText.clear();\n searchText.sendKeys('76');\n expectFriendNames(['John', 'Julie'], 'friend');\n });\n\n it('should search in specific fields when filtering with a predicate object', function() {\n var searchAny = element(by.model('search.$'));\n searchAny.clear();\n searchAny.sendKeys('i');\n expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');\n });\n it('should use a equal comparison when comparator is true', function() {\n var searchName = element(by.model('search.name'));\n var strict = element(by.model('strict'));\n searchName.clear();\n searchName.sendKeys('Julie');\n strict.click();\n expectFriendNames(['Julie'], 'friendObj');\n });\n \n
\n */\nfunction filterFilter() {\n return function(array, expression, comparator) {\n if (!isArray(array)) return array;\n\n var predicateFn;\n var matchAgainstAnyProp;\n\n switch (typeof expression) {\n case 'function':\n predicateFn = expression;\n break;\n case 'boolean':\n case 'number':\n case 'string':\n matchAgainstAnyProp = true;\n //jshint -W086\n case 'object':\n //jshint +W086\n predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);\n break;\n default:\n return array;\n }\n\n return array.filter(predicateFn);\n };\n}\n\n// Helper functions for `filterFilter`\nfunction createPredicateFn(expression, comparator, matchAgainstAnyProp) {\n var shouldMatchPrimitives = isObject(expression) && ('$' in expression);\n var predicateFn;\n\n if (comparator === true) {\n comparator = equals;\n } else if (!isFunction(comparator)) {\n comparator = function(actual, expected) {\n if (isObject(actual) || isObject(expected)) {\n // Prevent an object to be considered equal to a string like `'[object'`\n return false;\n }\n\n actual = lowercase('' + actual);\n expected = lowercase('' + expected);\n return actual.indexOf(expected) !== -1;\n };\n }\n\n predicateFn = function(item) {\n if (shouldMatchPrimitives && !isObject(item)) {\n return deepCompare(item, expression.$, comparator, false);\n }\n return deepCompare(item, expression, comparator, matchAgainstAnyProp);\n };\n\n return predicateFn;\n}\n\nfunction deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {\n var actualType = typeof actual;\n var expectedType = typeof expected;\n\n if ((expectedType === 'string') && (expected.charAt(0) === '!')) {\n return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);\n } else if (isArray(actual)) {\n // In case `actual` is an array, consider it a match\n // if ANY of it's items matches `expected`\n return actual.some(function(item) {\n return deepCompare(item, expected, comparator, matchAgainstAnyProp);\n });\n }\n\n switch (actualType) {\n case 'object':\n var key;\n if (matchAgainstAnyProp) {\n for (key in actual) {\n if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {\n return true;\n }\n }\n return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);\n } else if (expectedType === 'object') {\n for (key in expected) {\n var expectedVal = expected[key];\n if (isFunction(expectedVal)) {\n continue;\n }\n\n var matchAnyProperty = key === '$';\n var actualVal = matchAnyProperty ? actual : actual[key];\n if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) {\n return false;\n }\n }\n return true;\n } else {\n return comparator(actual, expected);\n }\n break;\n case 'function':\n return false;\n default:\n return comparator(actual, expected);\n }\n}\n\n/**\n * @ngdoc filter\n * @name currency\n * @kind function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale\n * @returns {string} Formatted number.\n *\n *\n * @example\n \n \n \n
\n
\n default currency symbol ($): {{amount | currency}}
\n custom currency identifier (USD$): {{amount | currency:\"USD$\"}}\n no fractions (0): {{amount | currency:\"USD$\":0}}\n
\n
\n \n it('should init with 1234.56', function() {\n expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');\n expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56');\n expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235');\n });\n it('should update', function() {\n if (browser.params.browser == 'safari') {\n // Safari does not understand the minus key. See\n // https://github.com/angular/protractor/issues/481\n return;\n }\n element(by.model('amount')).clear();\n element(by.model('amount')).sendKeys('-1234');\n expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');\n expect(element(by.id('currency-custom')).getText()).toBe('(USD$1,234.00)');\n expect(element(by.id('currency-no-fractions')).getText()).toBe('(USD$1,234)');\n });\n \n
\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n var formats = $locale.NUMBER_FORMATS;\n return function(amount, currencySymbol, fractionSize) {\n if (isUndefined(currencySymbol)) {\n currencySymbol = formats.CURRENCY_SYM;\n }\n\n if (isUndefined(fractionSize)) {\n fractionSize = formats.PATTERNS[1].maxFrac;\n }\n\n // if null or undefined pass it through\n return (amount == null)\n ? amount\n : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).\n replace(/\\u00A4/g, currencySymbol);\n };\n}\n\n/**\n * @ngdoc filter\n * @name number\n * @kind function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} fractionSize Number of decimal places to round the number to.\n * If this is not provided then the fraction size is computed from the current locale's number\n * formatting pattern. In the case of the default locale, it will be 3.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n \n \n \n
\n Enter number:
\n Default formatting: {{val | number}}
\n No fractions: {{val | number:0}}
\n Negative number: {{-val | number:4}}\n
\n
\n \n it('should format numbers', function() {\n expect(element(by.id('number-default')).getText()).toBe('1,234.568');\n expect(element(by.binding('val | number:0')).getText()).toBe('1,235');\n expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');\n });\n\n it('should update', function() {\n element(by.model('val')).clear();\n element(by.model('val')).sendKeys('3374.333');\n expect(element(by.id('number-default')).getText()).toBe('3,374.333');\n expect(element(by.binding('val | number:0')).getText()).toBe('3,374');\n expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');\n });\n \n
\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n var formats = $locale.NUMBER_FORMATS;\n return function(number, fractionSize) {\n\n // if null or undefined pass it through\n return (number == null)\n ? number\n : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n fractionSize);\n };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n if (!isFinite(number) || isObject(number)) return '';\n\n var isNegative = number < 0;\n number = Math.abs(number);\n var numStr = number + '',\n formatedText = '',\n parts = [];\n\n var hasExponent = false;\n if (numStr.indexOf('e') !== -1) {\n var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n number = 0;\n } else {\n formatedText = numStr;\n hasExponent = true;\n }\n }\n\n if (!hasExponent) {\n var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n // determine fractionSize if it is not specified\n if (isUndefined(fractionSize)) {\n fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n }\n\n // safely round numbers in JS without hitting imprecisions of floating-point arithmetics\n // inspired by:\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round\n number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);\n\n var fraction = ('' + number).split(DECIMAL_SEP);\n var whole = fraction[0];\n fraction = fraction[1] || '';\n\n var i, pos = 0,\n lgroup = pattern.lgSize,\n group = pattern.gSize;\n\n if (whole.length >= (lgroup + group)) {\n pos = whole.length - lgroup;\n for (i = 0; i < pos; i++) {\n if ((pos - i) % group === 0 && i !== 0) {\n formatedText += groupSep;\n }\n formatedText += whole.charAt(i);\n }\n }\n\n for (i = pos; i < whole.length; i++) {\n if ((whole.length - i) % lgroup === 0 && i !== 0) {\n formatedText += groupSep;\n }\n formatedText += whole.charAt(i);\n }\n\n // format fraction part.\n while (fraction.length < fractionSize) {\n fraction += '0';\n }\n\n if (fractionSize && fractionSize !== \"0\") formatedText += decimalSep + fraction.substr(0, fractionSize);\n } else {\n if (fractionSize > 0 && number < 1) {\n formatedText = number.toFixed(fractionSize);\n number = parseFloat(formatedText);\n }\n }\n\n if (number === 0) {\n isNegative = false;\n }\n\n parts.push(isNegative ? pattern.negPre : pattern.posPre,\n formatedText,\n isNegative ? pattern.negSuf : pattern.posSuf);\n return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n var neg = '';\n if (num < 0) {\n neg = '-';\n num = -num;\n }\n num = '' + num;\n while (num.length < digits) num = '0' + num;\n if (trim)\n num = num.substr(num.length - digits);\n return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n offset = offset || 0;\n return function(date) {\n var value = date['get' + name]();\n if (offset > 0 || value > -offset)\n value += offset;\n if (value === 0 && offset == -12) value = 12;\n return padNumber(value, size, trim);\n };\n}\n\nfunction dateStrGetter(name, shortForm) {\n return function(date, formats) {\n var value = date['get' + name]();\n var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n return formats[get][value];\n };\n}\n\nfunction timeZoneGetter(date) {\n var zone = -1 * date.getTimezoneOffset();\n var paddedZone = (zone >= 0) ? \"+\" : \"\";\n\n paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +\n padNumber(Math.abs(zone % 60), 2);\n\n return paddedZone;\n}\n\nfunction getFirstThursdayOfYear(year) {\n // 0 = index of January\n var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay();\n // 4 = index of Thursday (+1 to account for 1st = 5)\n // 11 = index of *next* Thursday (+1 account for 1st = 12)\n return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst);\n}\n\nfunction getThursdayThisWeek(datetime) {\n return new Date(datetime.getFullYear(), datetime.getMonth(),\n // 4 = index of Thursday\n datetime.getDate() + (4 - datetime.getDay()));\n}\n\nfunction weekGetter(size) {\n return function(date) {\n var firstThurs = getFirstThursdayOfYear(date.getFullYear()),\n thisThurs = getThursdayThisWeek(date);\n\n var diff = +thisThurs - +firstThurs,\n result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week\n\n return padNumber(result, size);\n };\n}\n\nfunction ampmGetter(date, formats) {\n return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n yyyy: dateGetter('FullYear', 4),\n yy: dateGetter('FullYear', 2, 0, true),\n y: dateGetter('FullYear', 1),\n MMMM: dateStrGetter('Month'),\n MMM: dateStrGetter('Month', true),\n MM: dateGetter('Month', 2, 1),\n M: dateGetter('Month', 1, 1),\n dd: dateGetter('Date', 2),\n d: dateGetter('Date', 1),\n HH: dateGetter('Hours', 2),\n H: dateGetter('Hours', 1),\n hh: dateGetter('Hours', 2, -12),\n h: dateGetter('Hours', 1, -12),\n mm: dateGetter('Minutes', 2),\n m: dateGetter('Minutes', 1),\n ss: dateGetter('Seconds', 2),\n s: dateGetter('Seconds', 1),\n // while ISO 8601 requires fractions to be prefixed with `.` or `,`\n // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions\n sss: dateGetter('Milliseconds', 3),\n EEEE: dateStrGetter('Day'),\n EEE: dateStrGetter('Day', true),\n a: ampmGetter,\n Z: timeZoneGetter,\n ww: weekGetter(2),\n w: weekGetter(1)\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/,\n NUMBER_STRING = /^\\-?\\d+$/;\n\n/**\n * @ngdoc filter\n * @name date\n * @kind function\n *\n * @description\n * Formats `date` to a string based on the requested `format`.\n *\n * `format` string can be composed of the following elements:\n *\n * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n * * `'MMMM'`: Month in year (January-December)\n * * `'MMM'`: Month in year (Jan-Dec)\n * * `'MM'`: Month in year, padded (01-12)\n * * `'M'`: Month in year (1-12)\n * * `'dd'`: Day in month, padded (01-31)\n * * `'d'`: Day in month (1-31)\n * * `'EEEE'`: Day in Week,(Sunday-Saturday)\n * * `'EEE'`: Day in Week, (Sun-Sat)\n * * `'HH'`: Hour in day, padded (00-23)\n * * `'H'`: Hour in day (0-23)\n * * `'hh'`: Hour in AM/PM, padded (01-12)\n * * `'h'`: Hour in AM/PM, (1-12)\n * * `'mm'`: Minute in hour, padded (00-59)\n * * `'m'`: Minute in hour (0-59)\n * * `'ss'`: Second in minute, padded (00-59)\n * * `'s'`: Second in minute (0-59)\n * * `'sss'`: Millisecond in second, padded (000-999)\n * * `'a'`: AM/PM marker\n * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)\n * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year\n * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year\n *\n * `format` string can also be one of the following predefined\n * {@link guide/i18n localizable formats}:\n *\n * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n * (e.g. Sep 3, 2010 12:05:08 PM)\n * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 PM)\n * * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US locale\n * (e.g. Friday, September 3, 2010)\n * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010)\n * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010)\n * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM)\n * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM)\n *\n * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.\n * `\"h 'in the morning'\"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence\n * (e.g. `\"h 'o''clock'\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its\n * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is\n * specified in the string input, the time is considered to be in the local timezone.\n * @param {string=} format Formatting rules (see Description). If not specified,\n * `mediumDate` is used.\n * @param {string=} timezone Timezone to be used for formatting. Right now, only `'UTC'` is supported.\n * If not specified, the timezone of the browser will be used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n \n \n {{1288323623006 | date:'medium'}}:\n {{1288323623006 | date:'medium'}}
\n {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}:\n {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
\n {{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}:\n {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
\n {{1288323623006 | date:\"MM/dd/yyyy 'at' h:mma\"}}:\n {{'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"}}
\n
\n \n it('should format date', function() {\n expect(element(by.binding(\"1288323623006 | date:'medium'\")).getText()).\n toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n expect(element(by.binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).getText()).\n toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} (\\-|\\+)?\\d{4}/);\n expect(element(by.binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).getText()).\n toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n expect(element(by.binding(\"'1288323623006' | date:\\\"MM/dd/yyyy 'at' h:mma\\\"\")).getText()).\n toMatch(/10\\/2\\d\\/2010 at \\d{1,2}:\\d{2}(AM|PM)/);\n });\n \n
\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n // 1 2 3 4 5 6 7 8 9 10 11\n function jsonStringToDate(string) {\n var match;\n if (match = string.match(R_ISO8601_STR)) {\n var date = new Date(0),\n tzHour = 0,\n tzMin = 0,\n dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,\n timeSetter = match[8] ? date.setUTCHours : date.setHours;\n\n if (match[9]) {\n tzHour = int(match[9] + match[10]);\n tzMin = int(match[9] + match[11]);\n }\n dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));\n var h = int(match[4] || 0) - tzHour;\n var m = int(match[5] || 0) - tzMin;\n var s = int(match[6] || 0);\n var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);\n timeSetter.call(date, h, m, s, ms);\n return date;\n }\n return string;\n }\n\n\n return function(date, format, timezone) {\n var text = '',\n parts = [],\n fn, match;\n\n format = format || 'mediumDate';\n format = $locale.DATETIME_FORMATS[format] || format;\n if (isString(date)) {\n date = NUMBER_STRING.test(date) ? int(date) : jsonStringToDate(date);\n }\n\n if (isNumber(date)) {\n date = new Date(date);\n }\n\n if (!isDate(date)) {\n return date;\n }\n\n while (format) {\n match = DATE_FORMATS_SPLIT.exec(format);\n if (match) {\n parts = concat(parts, match, 1);\n format = parts.pop();\n } else {\n parts.push(format);\n format = null;\n }\n }\n\n if (timezone && timezone === 'UTC') {\n date = new Date(date.getTime());\n date.setMinutes(date.getMinutes() + date.getTimezoneOffset());\n }\n forEach(parts, function(value) {\n fn = DATE_FORMATS[value];\n text += fn ? fn(date, $locale.DATETIME_FORMATS)\n : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n });\n\n return text;\n };\n}\n\n\n/**\n * @ngdoc filter\n * @name json\n * @kind function\n *\n * @description\n * Allows you to convert a JavaScript object into JSON string.\n *\n * This filter is mostly useful for debugging. When using the double curly {{value}} notation\n * the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.\n * @returns {string} JSON string.\n *\n *\n * @example\n \n \n
{{ {'name':'value'} | json }}
\n
{{ {'name':'value'} | json:4 }}
\n
\n \n it('should jsonify filtered objects', function() {\n expect(element(by.id('default-spacing')).getText()).toMatch(/\\{\\n \"name\": ?\"value\"\\n}/);\n expect(element(by.id('custom-spacing')).getText()).toMatch(/\\{\\n \"name\": ?\"value\"\\n}/);\n });\n \n
\n *\n */\nfunction jsonFilter() {\n return function(object, spacing) {\n if (isUndefined(spacing)) {\n spacing = 2;\n }\n return toJson(object, spacing);\n };\n}\n\n\n/**\n * @ngdoc filter\n * @name lowercase\n * @kind function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name uppercase\n * @kind function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc filter\n * @name limitTo\n * @kind function\n *\n * @description\n * Creates a new array or string containing only a specified number of elements. The elements\n * are taken from either the beginning or the end of the source array, string or number, as specified by\n * the value and sign (positive or negative) of `limit`. If a number is used as input, it is\n * converted to a string.\n *\n * @param {Array|string|number} input Source array, string or number to be limited.\n * @param {string|number} limit The length of the returned array or string. If the `limit` number\n * is positive, `limit` number of items from the beginning of the source array/string are copied.\n * If the number is negative, `limit` number of items from the end of the source array/string\n * are copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array\n * had less than `limit` elements.\n *\n * @example\n \n \n \n
\n Limit {{numbers}} to: \n

Output numbers: {{ numbers | limitTo:numLimit }}

\n Limit {{letters}} to: \n

Output letters: {{ letters | limitTo:letterLimit }}

\n Limit {{longNumber}} to: \n

Output long number: {{ longNumber | limitTo:longNumberLimit }}

\n
\n
\n \n var numLimitInput = element(by.model('numLimit'));\n var letterLimitInput = element(by.model('letterLimit'));\n var longNumberLimitInput = element(by.model('longNumberLimit'));\n var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));\n var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));\n var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit'));\n\n it('should limit the number array to first three items', function() {\n expect(numLimitInput.getAttribute('value')).toBe('3');\n expect(letterLimitInput.getAttribute('value')).toBe('3');\n expect(longNumberLimitInput.getAttribute('value')).toBe('3');\n expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');\n expect(limitedLetters.getText()).toEqual('Output letters: abc');\n expect(limitedLongNumber.getText()).toEqual('Output long number: 234');\n });\n\n // There is a bug in safari and protractor that doesn't like the minus key\n // it('should update the output when -3 is entered', function() {\n // numLimitInput.clear();\n // numLimitInput.sendKeys('-3');\n // letterLimitInput.clear();\n // letterLimitInput.sendKeys('-3');\n // longNumberLimitInput.clear();\n // longNumberLimitInput.sendKeys('-3');\n // expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');\n // expect(limitedLetters.getText()).toEqual('Output letters: ghi');\n // expect(limitedLongNumber.getText()).toEqual('Output long number: 342');\n // });\n\n it('should not exceed the maximum size of input array', function() {\n numLimitInput.clear();\n numLimitInput.sendKeys('100');\n letterLimitInput.clear();\n letterLimitInput.sendKeys('100');\n longNumberLimitInput.clear();\n longNumberLimitInput.sendKeys('100');\n expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');\n expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');\n expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342');\n });\n \n
\n*/\nfunction limitToFilter() {\n return function(input, limit) {\n if (isNumber(input)) input = input.toString();\n if (!isArray(input) && !isString(input)) return input;\n\n if (Math.abs(Number(limit)) === Infinity) {\n limit = Number(limit);\n } else {\n limit = int(limit);\n }\n\n //NaN check on limit\n if (limit) {\n return limit > 0 ? input.slice(0, limit) : input.slice(limit);\n } else {\n return isString(input) ? \"\" : [];\n }\n };\n}\n\n/**\n * @ngdoc filter\n * @name orderBy\n * @kind function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically\n * for strings and numerically for numbers. Note: if you notice numbers are not being sorted\n * correctly, make sure they are actually being saved as numbers and not strings.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be\n * used by the comparator to determine the order of elements.\n *\n * Can be one of:\n *\n * - `function`: Getter function. The result of this function will be sorted using the\n * `<`, `=`, `>` operator.\n * - `string`: An Angular expression. The result of this expression is used to compare elements\n * (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by\n * 3 first characters of a property called `name`). The result of a constant expression\n * is interpreted as a property name to be used in comparisons (for example `\"special name\"`\n * to sort object by the value of their `special name` property). An expression can be\n * optionally prefixed with `+` or `-` to control ascending or descending sort order\n * (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array\n * element itself is used to compare where sorting.\n * - `Array`: An array of function or string predicates. The first predicate in the array\n * is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n * If the predicate is missing or empty then it defaults to `'+'`.\n *\n * @param {boolean=} reverse Reverse the order of the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n \n \n \n
\n
Sorting predicate = {{predicate}}; reverse = {{reverse}}
\n
\n [ unsorted ]\n \n \n \n \n \n \n \n \n \n \n \n
Name\n (^)Phone NumberAge
{{friend.name}}{{friend.phone}}{{friend.age}}
\n
\n
\n
\n *\n * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the\n * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the\n * desired parameters.\n *\n * Example:\n *\n * @example\n \n \n
\n \n \n \n \n \n \n \n \n \n \n \n
Name\n (^)Phone NumberAge
{{friend.name}}{{friend.phone}}{{friend.age}}
\n
\n
\n\n \n angular.module('orderByExample', [])\n .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {\n var orderBy = $filter('orderBy');\n $scope.friends = [\n { name: 'John', phone: '555-1212', age: 10 },\n { name: 'Mary', phone: '555-9876', age: 19 },\n { name: 'Mike', phone: '555-4321', age: 21 },\n { name: 'Adam', phone: '555-5678', age: 35 },\n { name: 'Julie', phone: '555-8765', age: 29 }\n ];\n $scope.order = function(predicate, reverse) {\n $scope.friends = orderBy($scope.friends, predicate, reverse);\n };\n $scope.order('-age',false);\n }]);\n \n
\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse) {\n return function(array, sortPredicate, reverseOrder) {\n if (!(isArrayLike(array))) return array;\n sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate];\n if (sortPredicate.length === 0) { sortPredicate = ['+']; }\n sortPredicate = sortPredicate.map(function(predicate) {\n var descending = false, get = predicate || identity;\n if (isString(predicate)) {\n if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n descending = predicate.charAt(0) == '-';\n predicate = predicate.substring(1);\n }\n if (predicate === '') {\n // Effectively no predicate was passed so we compare identity\n return reverseComparator(compare, descending);\n }\n get = $parse(predicate);\n if (get.constant) {\n var key = get();\n return reverseComparator(function(a, b) {\n return compare(a[key], b[key]);\n }, descending);\n }\n }\n return reverseComparator(function(a, b) {\n return compare(get(a),get(b));\n }, descending);\n });\n return slice.call(array).sort(reverseComparator(comparator, reverseOrder));\n\n function comparator(o1, o2) {\n for (var i = 0; i < sortPredicate.length; i++) {\n var comp = sortPredicate[i](o1, o2);\n if (comp !== 0) return comp;\n }\n return 0;\n }\n function reverseComparator(comp, descending) {\n return descending\n ? function(a, b) {return comp(b,a);}\n : comp;\n }\n\n function isPrimitive(value) {\n switch (typeof value) {\n case 'number': /* falls through */\n case 'boolean': /* falls through */\n case 'string':\n return true;\n default:\n return false;\n }\n }\n\n function objectToString(value) {\n if (value === null) return 'null';\n if (typeof value.valueOf === 'function') {\n value = value.valueOf();\n if (isPrimitive(value)) return value;\n }\n if (typeof value.toString === 'function') {\n value = value.toString();\n if (isPrimitive(value)) return value;\n }\n return '';\n }\n\n function compare(v1, v2) {\n var t1 = typeof v1;\n var t2 = typeof v2;\n if (t1 === t2 && t1 === \"object\") {\n v1 = objectToString(v1);\n v2 = objectToString(v2);\n }\n if (t1 === t2) {\n if (t1 === \"string\") {\n v1 = v1.toLowerCase();\n v2 = v2.toLowerCase();\n }\n if (v1 === v2) return 0;\n return v1 < v2 ? -1 : 1;\n } else {\n return t1 < t2 ? -1 : 1;\n }\n }\n };\n}\n\nfunction ngDirective(directive) {\n if (isFunction(directive)) {\n directive = {\n link: directive\n };\n }\n directive.restrict = directive.restrict || 'AC';\n return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of the html A tag so that the default action is prevented when\n * the href attribute is empty.\n *\n * This change permits the easy creation of action links with the `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * `Add Item`\n */\nvar htmlAnchorDirective = valueFn({\n restrict: 'E',\n compile: function(element, attr) {\n if (!attr.href && !attr.xlinkHref && !attr.name) {\n return function(scope, element) {\n // If the linked element is not an anchor tag anymore, do nothing\n if (element[0].nodeName.toLowerCase() !== 'a') return;\n\n // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.\n var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?\n 'xlink:href' : 'href';\n element.on('click', function(event) {\n // if we have no href url, then don't navigate anywhere.\n if (!element.attr(href)) {\n event.preventDefault();\n }\n });\n };\n }\n }\n});\n\n/**\n * @ngdoc directive\n * @name ngHref\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in an href attribute will\n * make the link go to the wrong URL if the user clicks it before\n * Angular has a chance to replace the `{{hash}}` markup with its\n * value. Until Angular replaces the markup the link will be broken\n * and will most likely return a 404 error. The `ngHref` directive\n * solves this problem.\n *\n * The wrong way to write it:\n * ```html\n * link1\n * ```\n *\n * The correct way to write it:\n * ```html\n * link1\n * ```\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes\n * in links and their different behaviors:\n \n \n
\n link 1 (link, don't reload)
\n link 2 (link, don't reload)
\n link 3 (link, reload!)
\n anchor (link, don't reload)
\n anchor (no link)
\n link (link, change location)\n
\n \n it('should execute ng-click but not reload when href without value', function() {\n element(by.id('link-1')).click();\n expect(element(by.model('value')).getAttribute('value')).toEqual('1');\n expect(element(by.id('link-1')).getAttribute('href')).toBe('');\n });\n\n it('should execute ng-click but not reload when href empty string', function() {\n element(by.id('link-2')).click();\n expect(element(by.model('value')).getAttribute('value')).toEqual('2');\n expect(element(by.id('link-2')).getAttribute('href')).toBe('');\n });\n\n it('should execute ng-click and change url when ng-href specified', function() {\n expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\\/123$/);\n\n element(by.id('link-3')).click();\n\n // At this point, we navigate away from an Angular page, so we need\n // to use browser.driver to get the base webdriver.\n\n browser.wait(function() {\n return browser.driver.getCurrentUrl().then(function(url) {\n return url.match(/\\/123$/);\n });\n }, 5000, 'page should navigate to /123');\n });\n\n xit('should execute ng-click but not reload when href empty string and name specified', function() {\n element(by.id('link-4')).click();\n expect(element(by.model('value')).getAttribute('value')).toEqual('4');\n expect(element(by.id('link-4')).getAttribute('href')).toBe('');\n });\n\n it('should execute ng-click but not reload when no href but name specified', function() {\n element(by.id('link-5')).click();\n expect(element(by.model('value')).getAttribute('value')).toEqual('5');\n expect(element(by.id('link-5')).getAttribute('href')).toBe(null);\n });\n\n it('should only change url when only ng-href', function() {\n element(by.model('value')).clear();\n element(by.model('value')).sendKeys('6');\n expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\\/6$/);\n\n element(by.id('link-6')).click();\n\n // At this point, we navigate away from an Angular page, so we need\n // to use browser.driver to get the base webdriver.\n browser.wait(function() {\n return browser.driver.getCurrentUrl().then(function(url) {\n return url.match(/\\/6$/);\n });\n }, 5000, 'page should navigate to /6');\n });\n \n
\n */\n\n/**\n * @ngdoc directive\n * @name ngSrc\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * ```html\n * \n * ```\n *\n * The correct way to write it:\n * ```html\n * \n * ```\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ngSrcset\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrcset` directive solves this problem.\n *\n * The buggy way to write it:\n * ```html\n * \n * ```\n *\n * The correct way to write it:\n * ```html\n * \n * ```\n *\n * @element IMG\n * @param {template} ngSrcset any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ngDisabled\n * @restrict A\n * @priority 100\n *\n * @description\n *\n * We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * ```html\n *
\n * \n *
\n * ```\n *\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as disabled. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngDisabled` directive solves this problem for the `disabled` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n *\n * @example\n \n \n Click me to toggle:
\n \n
\n \n it('should toggle button', function() {\n expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();\n element(by.model('checked')).click();\n expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();\n });\n \n
\n *\n * @element INPUT\n * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,\n * then special attribute \"disabled\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngChecked\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as checked. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngChecked` directive solves this problem for the `checked` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n \n \n Check me to check both:
\n \n
\n \n it('should check both checkBoxes', function() {\n expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy();\n element(by.model('master')).click();\n expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy();\n });\n \n
\n *\n * @element INPUT\n * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,\n * then special attribute \"checked\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngReadonly\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as readonly. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngReadonly` directive solves this problem for the `readonly` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n \n \n Check me to make text readonly:
\n \n
\n \n it('should toggle readonly attr', function() {\n expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeFalsy();\n element(by.model('checked')).click();\n expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeTruthy();\n });\n \n
\n *\n * @element INPUT\n * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,\n * then special attribute \"readonly\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngSelected\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as selected. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngSelected` directive solves this problem for the `selected` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n *\n * @example\n \n \n Check me to select:
\n \n
\n \n it('should select Greetings!', function() {\n expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();\n element(by.model('selected')).click();\n expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();\n });\n \n
\n *\n * @element OPTION\n * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,\n * then special attribute \"selected\" will be set on the element\n */\n\n/**\n * @ngdoc directive\n * @name ngOpen\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as open. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngOpen` directive solves this problem for the `open` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n \n \n Check me check multiple:
\n
\n Show/Hide me\n
\n
\n \n it('should toggle open', function() {\n expect(element(by.id('details')).getAttribute('open')).toBeFalsy();\n element(by.model('open')).click();\n expect(element(by.id('details')).getAttribute('open')).toBeTruthy();\n });\n \n
\n *\n * @element DETAILS\n * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,\n * then special attribute \"open\" will be set on the element\n */\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n // binding to multiple is not supported\n if (propName == \"multiple\") return;\n\n var normalized = directiveNormalize('ng-' + attrName);\n ngAttributeAliasDirectives[normalized] = function() {\n return {\n restrict: 'A',\n priority: 100,\n link: function(scope, element, attr) {\n scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n attr.$set(attrName, !!value);\n });\n }\n };\n };\n});\n\n// aliased input attrs are evaluated\nforEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {\n ngAttributeAliasDirectives[ngAttr] = function() {\n return {\n priority: 100,\n link: function(scope, element, attr) {\n //special case ngPattern when a literal regular expression value\n //is used as the expression (this way we don't have to watch anything).\n if (ngAttr === \"ngPattern\" && attr.ngPattern.charAt(0) == \"/\") {\n var match = attr.ngPattern.match(REGEX_STRING_REGEXP);\n if (match) {\n attr.$set(\"ngPattern\", new RegExp(match[1], match[2]));\n return;\n }\n }\n\n scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {\n attr.$set(ngAttr, value);\n });\n }\n };\n };\n});\n\n// ng-src, ng-srcset, ng-href are interpolated\nforEach(['src', 'srcset', 'href'], function(attrName) {\n var normalized = directiveNormalize('ng-' + attrName);\n ngAttributeAliasDirectives[normalized] = function() {\n return {\n priority: 99, // it needs to run after the attributes are interpolated\n link: function(scope, element, attr) {\n var propName = attrName,\n name = attrName;\n\n if (attrName === 'href' &&\n toString.call(element.prop('href')) === '[object SVGAnimatedString]') {\n name = 'xlinkHref';\n attr.$attr[name] = 'xlink:href';\n propName = null;\n }\n\n attr.$observe(normalized, function(value) {\n if (!value) {\n if (attrName === 'href') {\n attr.$set(name, null);\n }\n return;\n }\n\n attr.$set(name, value);\n\n // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n // to set the property as well to achieve the desired effect.\n // we use attr[attrName] value since $set can sanitize the url.\n if (msie && propName) element.prop(propName, attr[name]);\n });\n }\n };\n };\n});\n\n/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true\n */\nvar nullFormCtrl = {\n $addControl: noop,\n $$renameControl: nullFormRenameControl,\n $removeControl: noop,\n $setValidity: noop,\n $setDirty: noop,\n $setPristine: noop,\n $setSubmitted: noop\n},\nSUBMITTED_CLASS = 'ng-submitted';\n\nfunction nullFormRenameControl(control, name) {\n control.$name = name;\n}\n\n/**\n * @ngdoc type\n * @name form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n * @property {boolean} $submitted True if user has submitted the form even if its invalid.\n *\n * @property {Object} $error Is an object hash, containing references to controls or\n * forms with failing validators, where:\n *\n * - keys are validation tokens (error names),\n * - values are arrays of controls or forms that have a failing validator for given error name.\n *\n * Built-in validation tokens:\n *\n * - `email`\n * - `max`\n * - `maxlength`\n * - `min`\n * - `minlength`\n * - `number`\n * - `pattern`\n * - `required`\n * - `url`\n * - `date`\n * - `datetimelocal`\n * - `time`\n * - `week`\n * - `month`\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as the state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate'];\nfunction FormController(element, attrs, $scope, $animate, $interpolate) {\n var form = this,\n controls = [];\n\n var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl;\n\n // init state\n form.$error = {};\n form.$$success = {};\n form.$pending = undefined;\n form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope);\n form.$dirty = false;\n form.$pristine = true;\n form.$valid = true;\n form.$invalid = false;\n form.$submitted = false;\n\n parentForm.$addControl(form);\n\n /**\n * @ngdoc method\n * @name form.FormController#$rollbackViewValue\n *\n * @description\n * Rollback all form controls pending updates to the `$modelValue`.\n *\n * Updates may be pending by a debounced event or because the input is waiting for a some future\n * event defined in `ng-model-options`. This method is typically needed by the reset button of\n * a form that uses `ng-model-options` to pend updates.\n */\n form.$rollbackViewValue = function() {\n forEach(controls, function(control) {\n control.$rollbackViewValue();\n });\n };\n\n /**\n * @ngdoc method\n * @name form.FormController#$commitViewValue\n *\n * @description\n * Commit all form controls pending updates to the `$modelValue`.\n *\n * Updates may be pending by a debounced event or because the input is waiting for a some future\n * event defined in `ng-model-options`. This method is rarely needed as `NgModelController`\n * usually handles calling this in response to input events.\n */\n form.$commitViewValue = function() {\n forEach(controls, function(control) {\n control.$commitViewValue();\n });\n };\n\n /**\n * @ngdoc method\n * @name form.FormController#$addControl\n *\n * @description\n * Register a control with the form.\n *\n * Input elements using ngModelController do this automatically when they are linked.\n */\n form.$addControl = function(control) {\n // Breaking change - before, inputs whose name was \"hasOwnProperty\" were quietly ignored\n // and not added to the scope. Now we throw an error.\n assertNotHasOwnProperty(control.$name, 'input');\n controls.push(control);\n\n if (control.$name) {\n form[control.$name] = control;\n }\n };\n\n // Private API: rename a form control\n form.$$renameControl = function(control, newName) {\n var oldName = control.$name;\n\n if (form[oldName] === control) {\n delete form[oldName];\n }\n form[newName] = control;\n control.$name = newName;\n };\n\n /**\n * @ngdoc method\n * @name form.FormController#$removeControl\n *\n * @description\n * Deregister a control from the form.\n *\n * Input elements using ngModelController do this automatically when they are destroyed.\n */\n form.$removeControl = function(control) {\n if (control.$name && form[control.$name] === control) {\n delete form[control.$name];\n }\n forEach(form.$pending, function(value, name) {\n form.$setValidity(name, null, control);\n });\n forEach(form.$error, function(value, name) {\n form.$setValidity(name, null, control);\n });\n forEach(form.$$success, function(value, name) {\n form.$setValidity(name, null, control);\n });\n\n arrayRemove(controls, control);\n };\n\n\n /**\n * @ngdoc method\n * @name form.FormController#$setValidity\n *\n * @description\n * Sets the validity of a form control.\n *\n * This method will also propagate to parent forms.\n */\n addSetValidityMethod({\n ctrl: this,\n $element: element,\n set: function(object, property, controller) {\n var list = object[property];\n if (!list) {\n object[property] = [controller];\n } else {\n var index = list.indexOf(controller);\n if (index === -1) {\n list.push(controller);\n }\n }\n },\n unset: function(object, property, controller) {\n var list = object[property];\n if (!list) {\n return;\n }\n arrayRemove(list, controller);\n if (list.length === 0) {\n delete object[property];\n }\n },\n parentForm: parentForm,\n $animate: $animate\n });\n\n /**\n * @ngdoc method\n * @name form.FormController#$setDirty\n *\n * @description\n * Sets the form to a dirty state.\n *\n * This method can be called to add the 'ng-dirty' class and set the form to a dirty\n * state (ng-dirty class). This method will also propagate to parent forms.\n */\n form.$setDirty = function() {\n $animate.removeClass(element, PRISTINE_CLASS);\n $animate.addClass(element, DIRTY_CLASS);\n form.$dirty = true;\n form.$pristine = false;\n parentForm.$setDirty();\n };\n\n /**\n * @ngdoc method\n * @name form.FormController#$setPristine\n *\n * @description\n * Sets the form to its pristine state.\n *\n * This method can be called to remove the 'ng-dirty' class and set the form to its pristine\n * state (ng-pristine class). This method will also propagate to all the controls contained\n * in this form.\n *\n * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after\n * saving or resetting it.\n */\n form.$setPristine = function() {\n $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);\n form.$dirty = false;\n form.$pristine = true;\n form.$submitted = false;\n forEach(controls, function(control) {\n control.$setPristine();\n });\n };\n\n /**\n * @ngdoc method\n * @name form.FormController#$setUntouched\n *\n * @description\n * Sets the form to its untouched state.\n *\n * This method can be called to remove the 'ng-touched' class and set the form controls to their\n * untouched state (ng-untouched class).\n *\n * Setting a form controls back to their untouched state is often useful when setting the form\n * back to its pristine state.\n */\n form.$setUntouched = function() {\n forEach(controls, function(control) {\n control.$setUntouched();\n });\n };\n\n /**\n * @ngdoc method\n * @name form.FormController#$setSubmitted\n *\n * @description\n * Sets the form to its submitted state.\n */\n form.$setSubmitted = function() {\n $animate.addClass(element, SUBMITTED_CLASS);\n form.$submitted = true;\n parentForm.$setSubmitted();\n };\n}\n\n/**\n * @ngdoc directive\n * @name ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * Note: the purpose of `ngForm` is to group controls,\n * but not to be a replacement for the `
` tag with all of its capabilities\n * (e.g. posting to the server, ...).\n *\n * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into\n * related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link form.FormController FormController}.\n *\n * If the `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In Angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However, browsers do not allow nesting of `` elements, so\n * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to\n * `` but can be nested. This allows you to have nested forms, which is very useful when\n * using Angular validation directives in forms that are dynamically generated using the\n * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`\n * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an\n * `ngForm` directive and nest these in an outer `form` element.\n *\n *\n * # CSS classes\n * - `ng-valid` is set if the form is valid.\n * - `ng-invalid` is set if the form is invalid.\n * - `ng-pristine` is set if the form is pristine.\n * - `ng-dirty` is set if the form is dirty.\n * - `ng-submitted` is set if the form was submitted.\n *\n * Keep in mind that ngAnimate can detect each of these classes when added and removed.\n *\n *\n * # Submitting a form and preventing the default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in an application-specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n * button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}\n * or {@link ng.directive:ngClick ngClick} directives.\n * This is because of the following form submission rules in the HTML specification:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is\n * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`\n * to have access to the updated model.\n *\n * ## Animation Hooks\n *\n * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.\n * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any\n * other validations that are performed within the form. Animations in ngForm are similar to how\n * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well\n * as JS animations.\n *\n * The following example shows a simple way to utilize CSS transitions to style a form element\n * that has been rendered as invalid after it has been validated:\n *\n *
\n * //be sure to include ngAnimate as a module to hook into more\n * //advanced animations\n * .my-form {\n *   transition:0.5s linear all;\n *   background: white;\n * }\n * .my-form.ng-invalid {\n *   background: red;\n *   color:white;\n * }\n * 
\n *\n * @example\n \n \n \n \n \n userType: \n Required!
\n userType = {{userType}}
\n myForm.input.$valid = {{myForm.input.$valid}}
\n myForm.input.$error = {{myForm.input.$error}}
\n myForm.$valid = {{myForm.$valid}}
\n myForm.$error.required = {{!!myForm.$error.required}}
\n \n
\n \n it('should initialize to model', function() {\n var userType = element(by.binding('userType'));\n var valid = element(by.binding('myForm.input.$valid'));\n\n expect(userType.getText()).toContain('guest');\n expect(valid.getText()).toContain('true');\n });\n\n it('should be invalid if empty', function() {\n var userType = element(by.binding('userType'));\n var valid = element(by.binding('myForm.input.$valid'));\n var userInput = element(by.model('userType'));\n\n userInput.clear();\n userInput.sendKeys('');\n\n expect(userType.getText()).toEqual('userType =');\n expect(valid.getText()).toContain('false');\n });\n \n
\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n * related scope, under this name.\n */\nvar formDirectiveFactory = function(isNgForm) {\n return ['$timeout', function($timeout) {\n var formDirective = {\n name: 'form',\n restrict: isNgForm ? 'EAC' : 'E',\n controller: FormController,\n compile: function ngFormCompile(formElement) {\n // Setup initial state of the control\n formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS);\n\n return {\n pre: function ngFormPreLink(scope, formElement, attr, controller) {\n // if `action` attr is not present on the form, prevent the default action (submission)\n if (!('action' in attr)) {\n // we can't use jq events because if a form is destroyed during submission the default\n // action is not prevented. see #1238\n //\n // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n // page reload if the form was destroyed by submission of the form via a click handler\n // on a button in the form. Looks like an IE9 specific bug.\n var handleFormSubmission = function(event) {\n scope.$apply(function() {\n controller.$commitViewValue();\n controller.$setSubmitted();\n });\n\n event.preventDefault();\n };\n\n addEventListenerFn(formElement[0], 'submit', handleFormSubmission);\n\n // unregister the preventDefault listener so that we don't not leak memory but in a\n // way that will achieve the prevention of the default action.\n formElement.on('$destroy', function() {\n $timeout(function() {\n removeEventListenerFn(formElement[0], 'submit', handleFormSubmission);\n }, 0, false);\n });\n }\n\n var parentFormCtrl = controller.$$parentForm,\n alias = controller.$name;\n\n if (alias) {\n setter(scope, null, alias, controller, alias);\n attr.$observe(attr.name ? 'name' : 'ngForm', function(newValue) {\n if (alias === newValue) return;\n setter(scope, null, alias, undefined, alias);\n alias = newValue;\n setter(scope, null, alias, controller, alias);\n parentFormCtrl.$$renameControl(controller, alias);\n });\n }\n formElement.on('$destroy', function() {\n parentFormCtrl.$removeControl(controller);\n if (alias) {\n setter(scope, null, alias, undefined, alias);\n }\n extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n });\n }\n };\n }\n };\n\n return formDirective;\n }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\n/* global VALID_CLASS: false,\n INVALID_CLASS: false,\n PRISTINE_CLASS: false,\n DIRTY_CLASS: false,\n UNTOUCHED_CLASS: false,\n TOUCHED_CLASS: false,\n $ngModelMinErr: false,\n*/\n\n// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231\nvar ISO_DATE_REGEXP = /\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d:[0-5]\\d|Z)/;\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\nvar DATE_REGEXP = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\nvar DATETIMELOCAL_REGEXP = /^(\\d{4})-(\\d\\d)-(\\d\\d)T(\\d\\d):(\\d\\d)(?::(\\d\\d)(\\.\\d{1,3})?)?$/;\nvar WEEK_REGEXP = /^(\\d{4})-W(\\d\\d)$/;\nvar MONTH_REGEXP = /^(\\d{4})-(\\d\\d)$/;\nvar TIME_REGEXP = /^(\\d\\d):(\\d\\d)(?::(\\d\\d)(\\.\\d{1,3})?)?$/;\n\nvar inputType = {\n\n /**\n * @ngdoc input\n * @name input[text]\n *\n * @description\n * Standard HTML text input with angular data binding, inherited by most of the `input` elements.\n *\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Adds `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n * `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n * minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n * any length.\n * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n * that contains the regular expression body that will be converted to a regular expression\n * as in the ngPattern directive.\n * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n * a RegExp found by evaluating the Angular expression given in the attribute value.\n * If the expression evaluates to a RegExp object then this is used directly.\n * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n * characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n * interaction with the input element.\n * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n * This parameter is ignored for input[type=password] controls, which will never trim the\n * input.\n *\n * @example\n \n \n \n
\n Single word: \n \n Required!\n \n Single word only!\n\n text = {{example.text}}
\n myForm.input.$valid = {{myForm.input.$valid}}
\n myForm.input.$error = {{myForm.input.$error}}
\n myForm.$valid = {{myForm.$valid}}
\n myForm.$error.required = {{!!myForm.$error.required}}
\n
\n
\n \n var text = element(by.binding('example.text'));\n var valid = element(by.binding('myForm.input.$valid'));\n var input = element(by.model('example.text'));\n\n it('should initialize to model', function() {\n expect(text.getText()).toContain('guest');\n expect(valid.getText()).toContain('true');\n });\n\n it('should be invalid if empty', function() {\n input.clear();\n input.sendKeys('');\n\n expect(text.getText()).toEqual('text =');\n expect(valid.getText()).toContain('false');\n });\n\n it('should be invalid if multi word', function() {\n input.clear();\n input.sendKeys('hello world');\n\n expect(valid.getText()).toContain('false');\n });\n \n
\n */\n 'text': textInputType,\n\n /**\n * @ngdoc input\n * @name input[date]\n *\n * @description\n * Input with date validation and transformation. In browsers that do not yet support\n * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601\n * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many\n * modern browsers do not yet support this input type, it is important to provide cues to users on the\n * expected input format via a placeholder or label.\n *\n * The model must always be a Date object, otherwise Angular will throw an error.\n * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n *\n * The timezone to be used to read/write the `Date` instance in the model can be defined using\n * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n * valid ISO date string (yyyy-MM-dd).\n * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n * a valid ISO date string (yyyy-MM-dd).\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n * `required` when you want to data-bind to the `required` attribute.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n * interaction with the input element.\n *\n * @example\n \n \n \n
\n Pick a date in 2013:\n \n \n Required!\n \n Not a valid date!\n value = {{example.value | date: \"yyyy-MM-dd\"}}
\n myForm.input.$valid = {{myForm.input.$valid}}
\n myForm.input.$error = {{myForm.input.$error}}
\n myForm.$valid = {{myForm.$valid}}
\n myForm.$error.required = {{!!myForm.$error.required}}
\n
\n
\n \n var value = element(by.binding('example.value | date: \"yyyy-MM-dd\"'));\n var valid = element(by.binding('myForm.input.$valid'));\n var input = element(by.model('example.value'));\n\n // currently protractor/webdriver does not support\n // sending keys to all known HTML5 input controls\n // for various browsers (see https://github.com/angular/protractor/issues/562).\n function setInput(val) {\n // set the value of the element and force validation.\n var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n \"ipt.value = '\" + val + \"';\" +\n \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n browser.executeScript(scr);\n }\n\n it('should initialize to model', function() {\n expect(value.getText()).toContain('2013-10-22');\n expect(valid.getText()).toContain('myForm.input.$valid = true');\n });\n\n it('should be invalid if empty', function() {\n setInput('');\n expect(value.getText()).toEqual('value =');\n expect(valid.getText()).toContain('myForm.input.$valid = false');\n });\n\n it('should be invalid if over max', function() {\n setInput('2015-01-01');\n expect(value.getText()).toContain('');\n expect(valid.getText()).toContain('myForm.input.$valid = false');\n });\n \n
\n */\n 'date': createDateInputType('date', DATE_REGEXP,\n createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),\n 'yyyy-MM-dd'),\n\n /**\n * @ngdoc input\n * @name input[datetime-local]\n *\n * @description\n * Input with datetime validation and transformation. In browsers that do not yet support\n * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`.\n *\n * The model must always be a Date object, otherwise Angular will throw an error.\n * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n *\n * The timezone to be used to read/write the `Date` instance in the model can be defined using\n * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n * valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).\n * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n * a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n * `required` when you want to data-bind to the `required` attribute.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n * interaction with the input element.\n *\n * @example\n \n \n \n
\n Pick a date between in 2013:\n \n \n Required!\n \n Not a valid date!\n value = {{example.value | date: \"yyyy-MM-ddTHH:mm:ss\"}}
\n myForm.input.$valid = {{myForm.input.$valid}}
\n myForm.input.$error = {{myForm.input.$error}}
\n myForm.$valid = {{myForm.$valid}}
\n myForm.$error.required = {{!!myForm.$error.required}}
\n
\n
\n \n var value = element(by.binding('example.value | date: \"yyyy-MM-ddTHH:mm:ss\"'));\n var valid = element(by.binding('myForm.input.$valid'));\n var input = element(by.model('example.value'));\n\n // currently protractor/webdriver does not support\n // sending keys to all known HTML5 input controls\n // for various browsers (https://github.com/angular/protractor/issues/562).\n function setInput(val) {\n // set the value of the element and force validation.\n var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n \"ipt.value = '\" + val + \"';\" +\n \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n browser.executeScript(scr);\n }\n\n it('should initialize to model', function() {\n expect(value.getText()).toContain('2010-12-28T14:57:00');\n expect(valid.getText()).toContain('myForm.input.$valid = true');\n });\n\n it('should be invalid if empty', function() {\n setInput('');\n expect(value.getText()).toEqual('value =');\n expect(valid.getText()).toContain('myForm.input.$valid = false');\n });\n\n it('should be invalid if over max', function() {\n setInput('2015-01-01T23:59:00');\n expect(value.getText()).toContain('');\n expect(valid.getText()).toContain('myForm.input.$valid = false');\n });\n \n
\n */\n 'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP,\n createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']),\n 'yyyy-MM-ddTHH:mm:ss.sss'),\n\n /**\n * @ngdoc input\n * @name input[time]\n *\n * @description\n * Input with time validation and transformation. In browsers that do not yet support\n * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a\n * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.\n *\n * The model must always be a Date object, otherwise Angular will throw an error.\n * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n *\n * The timezone to be used to read/write the `Date` instance in the model can be defined using\n * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n * valid ISO time format (HH:mm:ss).\n * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a\n * valid ISO time format (HH:mm:ss).\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n * `required` when you want to data-bind to the `required` attribute.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n * interaction with the input element.\n *\n * @example\n \n \n \n
\n Pick a between 8am and 5pm:\n \n \n Required!\n \n Not a valid date!\n value = {{example.value | date: \"HH:mm:ss\"}}
\n myForm.input.$valid = {{myForm.input.$valid}}
\n myForm.input.$error = {{myForm.input.$error}}
\n myForm.$valid = {{myForm.$valid}}
\n myForm.$error.required = {{!!myForm.$error.required}}
\n
\n
\n \n var value = element(by.binding('example.value | date: \"HH:mm:ss\"'));\n var valid = element(by.binding('myForm.input.$valid'));\n var input = element(by.model('example.value'));\n\n // currently protractor/webdriver does not support\n // sending keys to all known HTML5 input controls\n // for various browsers (https://github.com/angular/protractor/issues/562).\n function setInput(val) {\n // set the value of the element and force validation.\n var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n \"ipt.value = '\" + val + \"';\" +\n \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n browser.executeScript(scr);\n }\n\n it('should initialize to model', function() {\n expect(value.getText()).toContain('14:57:00');\n expect(valid.getText()).toContain('myForm.input.$valid = true');\n });\n\n it('should be invalid if empty', function() {\n setInput('');\n expect(value.getText()).toEqual('value =');\n expect(valid.getText()).toContain('myForm.input.$valid = false');\n });\n\n it('should be invalid if over max', function() {\n setInput('23:59:00');\n expect(value.getText()).toContain('');\n expect(valid.getText()).toContain('myForm.input.$valid = false');\n });\n \n
\n */\n 'time': createDateInputType('time', TIME_REGEXP,\n createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']),\n 'HH:mm:ss.sss'),\n\n /**\n * @ngdoc input\n * @name input[week]\n *\n * @description\n * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support\n * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n * week format (yyyy-W##), for example: `2013-W02`.\n *\n * The model must always be a Date object, otherwise Angular will throw an error.\n * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n *\n * The timezone to be used to read/write the `Date` instance in the model can be defined using\n * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a\n * valid ISO week format (yyyy-W##).\n * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be\n * a valid ISO week format (yyyy-W##).\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n * `required` when you want to data-bind to the `required` attribute.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n * interaction with the input element.\n *\n * @example\n \n \n \n
\n Pick a date between in 2013:\n \n \n Required!\n \n Not a valid date!\n value = {{example.value | date: \"yyyy-Www\"}}
\n myForm.input.$valid = {{myForm.input.$valid}}
\n myForm.input.$error = {{myForm.input.$error}}
\n myForm.$valid = {{myForm.$valid}}
\n myForm.$error.required = {{!!myForm.$error.required}}
\n
\n
\n \n var value = element(by.binding('example.value | date: \"yyyy-Www\"'));\n var valid = element(by.binding('myForm.input.$valid'));\n var input = element(by.model('example.value'));\n\n // currently protractor/webdriver does not support\n // sending keys to all known HTML5 input controls\n // for various browsers (https://github.com/angular/protractor/issues/562).\n function setInput(val) {\n // set the value of the element and force validation.\n var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n \"ipt.value = '\" + val + \"';\" +\n \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n browser.executeScript(scr);\n }\n\n it('should initialize to model', function() {\n expect(value.getText()).toContain('2013-W01');\n expect(valid.getText()).toContain('myForm.input.$valid = true');\n });\n\n it('should be invalid if empty', function() {\n setInput('');\n expect(value.getText()).toEqual('value =');\n expect(valid.getText()).toContain('myForm.input.$valid = false');\n });\n\n it('should be invalid if over max', function() {\n setInput('2015-W01');\n expect(value.getText()).toContain('');\n expect(valid.getText()).toContain('myForm.input.$valid = false');\n });\n \n
\n */\n 'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'),\n\n /**\n * @ngdoc input\n * @name input[month]\n *\n * @description\n * Input with month validation and transformation. In browsers that do not yet support\n * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601\n * month format (yyyy-MM), for example: `2009-01`.\n *\n * The model must always be a Date object, otherwise Angular will throw an error.\n * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.\n * If the model is not set to the first of the month, the next view to model update will set it\n * to the first of the month.\n *\n * The timezone to be used to read/write the `Date` instance in the model can be defined using\n * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be\n * a valid ISO month format (yyyy-MM).\n * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must\n * be a valid ISO month format (yyyy-MM).\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n * `required` when you want to data-bind to the `required` attribute.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n * interaction with the input element.\n *\n * @example\n \n \n \n
\n Pick a month in 2013:\n \n \n Required!\n \n Not a valid month!\n value = {{example.value | date: \"yyyy-MM\"}}
\n myForm.input.$valid = {{myForm.input.$valid}}
\n myForm.input.$error = {{myForm.input.$error}}
\n myForm.$valid = {{myForm.$valid}}
\n myForm.$error.required = {{!!myForm.$error.required}}
\n
\n
\n \n var value = element(by.binding('example.value | date: \"yyyy-MM\"'));\n var valid = element(by.binding('myForm.input.$valid'));\n var input = element(by.model('example.value'));\n\n // currently protractor/webdriver does not support\n // sending keys to all known HTML5 input controls\n // for various browsers (https://github.com/angular/protractor/issues/562).\n function setInput(val) {\n // set the value of the element and force validation.\n var scr = \"var ipt = document.getElementById('exampleInput'); \" +\n \"ipt.value = '\" + val + \"';\" +\n \"angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('\" + val + \"'); });\";\n browser.executeScript(scr);\n }\n\n it('should initialize to model', function() {\n expect(value.getText()).toContain('2013-10');\n expect(valid.getText()).toContain('myForm.input.$valid = true');\n });\n\n it('should be invalid if empty', function() {\n setInput('');\n expect(value.getText()).toEqual('value =');\n expect(valid.getText()).toContain('myForm.input.$valid = false');\n });\n\n it('should be invalid if over max', function() {\n setInput('2015-01');\n expect(value.getText()).toContain('');\n expect(valid.getText()).toContain('myForm.input.$valid = false');\n });\n \n
\n */\n 'month': createDateInputType('month', MONTH_REGEXP,\n createDateParser(MONTH_REGEXP, ['yyyy', 'MM']),\n 'yyyy-MM'),\n\n /**\n * @ngdoc input\n * @name input[number]\n *\n * @description\n * Text input with number validation and transformation. Sets the `number` validation\n * error if not a valid number.\n *\n * The model must always be a number, otherwise Angular will throw an error.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n * `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n * minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n * any length.\n * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n * that contains the regular expression body that will be converted to a regular expression\n * as in the ngPattern directive.\n * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n * a RegExp found by evaluating the Angular expression given in the attribute value.\n * If the expression evaluates to a RegExp object then this is used directly.\n * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n * characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n * interaction with the input element.\n *\n * @example\n \n \n \n
\n Number: \n \n Required!\n \n Not valid number!\n value = {{example.value}}
\n myForm.input.$valid = {{myForm.input.$valid}}
\n myForm.input.$error = {{myForm.input.$error}}
\n myForm.$valid = {{myForm.$valid}}
\n myForm.$error.required = {{!!myForm.$error.required}}
\n
\n
\n \n var value = element(by.binding('example.value'));\n var valid = element(by.binding('myForm.input.$valid'));\n var input = element(by.model('example.value'));\n\n it('should initialize to model', function() {\n expect(value.getText()).toContain('12');\n expect(valid.getText()).toContain('true');\n });\n\n it('should be invalid if empty', function() {\n input.clear();\n input.sendKeys('');\n expect(value.getText()).toEqual('value =');\n expect(valid.getText()).toContain('false');\n });\n\n it('should be invalid if over max', function() {\n input.clear();\n input.sendKeys('123');\n expect(value.getText()).toEqual('value =');\n expect(valid.getText()).toContain('false');\n });\n \n
\n */\n 'number': numberInputType,\n\n\n /**\n * @ngdoc input\n * @name input[url]\n *\n * @description\n * Text input with URL validation. Sets the `url` validation error key if the content is not a\n * valid URL.\n *\n *
\n * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex\n * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify\n * the built-in validators (see the {@link guide/forms Forms guide})\n *
\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n * `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n * minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n * any length.\n * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n * that contains the regular expression body that will be converted to a regular expression\n * as in the ngPattern directive.\n * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n * a RegExp found by evaluating the Angular expression given in the attribute value.\n * If the expression evaluates to a RegExp object then this is used directly.\n * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n * characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n * interaction with the input element.\n *\n * @example\n \n \n \n
\n URL: \n \n Required!\n \n Not valid url!\n text = {{url.text}}
\n myForm.input.$valid = {{myForm.input.$valid}}
\n myForm.input.$error = {{myForm.input.$error}}
\n myForm.$valid = {{myForm.$valid}}
\n myForm.$error.required = {{!!myForm.$error.required}}
\n myForm.$error.url = {{!!myForm.$error.url}}
\n
\n
\n \n var text = element(by.binding('url.text'));\n var valid = element(by.binding('myForm.input.$valid'));\n var input = element(by.model('url.text'));\n\n it('should initialize to model', function() {\n expect(text.getText()).toContain('http://google.com');\n expect(valid.getText()).toContain('true');\n });\n\n it('should be invalid if empty', function() {\n input.clear();\n input.sendKeys('');\n\n expect(text.getText()).toEqual('text =');\n expect(valid.getText()).toContain('false');\n });\n\n it('should be invalid if not url', function() {\n input.clear();\n input.sendKeys('box');\n\n expect(valid.getText()).toContain('false');\n });\n \n
\n */\n 'url': urlInputType,\n\n\n /**\n * @ngdoc input\n * @name input[email]\n *\n * @description\n * Text input with email validation. Sets the `email` validation error key if not a valid email\n * address.\n *\n *
\n * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex\n * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can\n * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide})\n *
\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n * `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n * minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of\n * any length.\n * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string\n * that contains the regular expression body that will be converted to a regular expression\n * as in the ngPattern directive.\n * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match\n * a RegExp found by evaluating the Angular expression given in the attribute value.\n * If the expression evaluates to a RegExp object then this is used directly.\n * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$`\n * characters. For instance, `\"abc\"` will be converted to `new RegExp('^abc$')`.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n * interaction with the input element.\n *\n * @example\n \n \n \n
\n Email: \n \n Required!\n \n Not valid email!\n text = {{email.text}}
\n myForm.input.$valid = {{myForm.input.$valid}}
\n myForm.input.$error = {{myForm.input.$error}}
\n myForm.$valid = {{myForm.$valid}}
\n myForm.$error.required = {{!!myForm.$error.required}}
\n myForm.$error.email = {{!!myForm.$error.email}}
\n
\n
\n \n var text = element(by.binding('email.text'));\n var valid = element(by.binding('myForm.input.$valid'));\n var input = element(by.model('email.text'));\n\n it('should initialize to model', function() {\n expect(text.getText()).toContain('me@example.com');\n expect(valid.getText()).toContain('true');\n });\n\n it('should be invalid if empty', function() {\n input.clear();\n input.sendKeys('');\n expect(text.getText()).toEqual('text =');\n expect(valid.getText()).toContain('false');\n });\n\n it('should be invalid if not email', function() {\n input.clear();\n input.sendKeys('xxx');\n\n expect(valid.getText()).toContain('false');\n });\n \n
\n */\n 'email': emailInputType,\n\n\n /**\n * @ngdoc input\n * @name input[radio]\n *\n * @description\n * HTML radio button.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string} value The value to which the expression should be set when selected.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n * interaction with the input element.\n * @param {string} ngValue Angular expression which sets the value to which the expression should\n * be set when selected.\n *\n * @example\n \n \n \n
\n Red
\n Green
\n Blue
\n color = {{color.name | json}}
\n
\n Note that `ng-value=\"specialValue\"` sets radio item's value to be the value of `$scope.specialValue`.\n
\n \n it('should change state', function() {\n var color = element(by.binding('color.name'));\n\n expect(color.getText()).toContain('blue');\n\n element.all(by.model('color.name')).get(0).click();\n\n expect(color.getText()).toContain('red');\n });\n \n
\n */\n 'radio': radioInputType,\n\n\n /**\n * @ngdoc input\n * @name input[checkbox]\n *\n * @description\n * HTML checkbox.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {expression=} ngTrueValue The value to which the expression should be set when selected.\n * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n * interaction with the input element.\n *\n * @example\n \n \n \n
\n Value1:
\n Value2:
\n value1 = {{checkboxModel.value1}}
\n value2 = {{checkboxModel.value2}}
\n
\n
\n \n it('should change state', function() {\n var value1 = element(by.binding('checkboxModel.value1'));\n var value2 = element(by.binding('checkboxModel.value2'));\n\n expect(value1.getText()).toContain('true');\n expect(value2.getText()).toContain('YES');\n\n element(by.model('checkboxModel.value1')).click();\n element(by.model('checkboxModel.value2')).click();\n\n expect(value1.getText()).toContain('false');\n expect(value2.getText()).toContain('NO');\n });\n \n
\n */\n 'checkbox': checkboxInputType,\n\n 'hidden': noop,\n 'button': noop,\n 'submit': noop,\n 'reset': noop,\n 'file': noop\n};\n\nfunction stringBasedInputType(ctrl) {\n ctrl.$formatters.push(function(value) {\n return ctrl.$isEmpty(value) ? value : value.toString();\n });\n}\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n stringBasedInputType(ctrl);\n}\n\nfunction baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n var type = lowercase(element[0].type);\n\n // In composition mode, users are still inputing intermediate text buffer,\n // hold the listener until composition is done.\n // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent\n if (!$sniffer.android) {\n var composing = false;\n\n element.on('compositionstart', function(data) {\n composing = true;\n });\n\n element.on('compositionend', function() {\n composing = false;\n listener();\n });\n }\n\n var listener = function(ev) {\n if (timeout) {\n $browser.defer.cancel(timeout);\n timeout = null;\n }\n if (composing) return;\n var value = element.val(),\n event = ev && ev.type;\n\n // By default we will trim the value\n // If the attribute ng-trim exists we will avoid trimming\n // If input type is 'password', the value is never trimmed\n if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {\n value = trim(value);\n }\n\n // If a control is suffering from bad input (due to native validators), browsers discard its\n // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the\n // control's value is the same empty value twice in a row.\n if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) {\n ctrl.$setViewValue(value, event);\n }\n };\n\n // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n // input event on backspace, delete or cut\n if ($sniffer.hasEvent('input')) {\n element.on('input', listener);\n } else {\n var timeout;\n\n var deferListener = function(ev, input, origValue) {\n if (!timeout) {\n timeout = $browser.defer(function() {\n timeout = null;\n if (!input || input.value !== origValue) {\n listener(ev);\n }\n });\n }\n };\n\n element.on('keydown', function(event) {\n var key = event.keyCode;\n\n // ignore\n // command modifiers arrows\n if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n deferListener(event, this, this.value);\n });\n\n // if user modifies input value using context menu in IE, we need \"paste\" and \"cut\" events to catch it\n if ($sniffer.hasEvent('paste')) {\n element.on('paste cut', deferListener);\n }\n }\n\n // if user paste into input using mouse on older browser\n // or form autocomplete on newer browser, we need \"change\" event to catch it\n element.on('change', listener);\n\n ctrl.$render = function() {\n element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n };\n}\n\nfunction weekParser(isoWeek, existingDate) {\n if (isDate(isoWeek)) {\n return isoWeek;\n }\n\n if (isString(isoWeek)) {\n WEEK_REGEXP.lastIndex = 0;\n var parts = WEEK_REGEXP.exec(isoWeek);\n if (parts) {\n var year = +parts[1],\n week = +parts[2],\n hours = 0,\n minutes = 0,\n seconds = 0,\n milliseconds = 0,\n firstThurs = getFirstThursdayOfYear(year),\n addDays = (week - 1) * 7;\n\n if (existingDate) {\n hours = existingDate.getHours();\n minutes = existingDate.getMinutes();\n seconds = existingDate.getSeconds();\n milliseconds = existingDate.getMilliseconds();\n }\n\n return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds);\n }\n }\n\n return NaN;\n}\n\nfunction createDateParser(regexp, mapping) {\n return function(iso, date) {\n var parts, map;\n\n if (isDate(iso)) {\n return iso;\n }\n\n if (isString(iso)) {\n // When a date is JSON'ified to wraps itself inside of an extra\n // set of double quotes. This makes the date parsing code unable\n // to match the date string and parse it as a date.\n if (iso.charAt(0) == '\"' && iso.charAt(iso.length - 1) == '\"') {\n iso = iso.substring(1, iso.length - 1);\n }\n if (ISO_DATE_REGEXP.test(iso)) {\n return new Date(iso);\n }\n regexp.lastIndex = 0;\n parts = regexp.exec(iso);\n\n if (parts) {\n parts.shift();\n if (date) {\n map = {\n yyyy: date.getFullYear(),\n MM: date.getMonth() + 1,\n dd: date.getDate(),\n HH: date.getHours(),\n mm: date.getMinutes(),\n ss: date.getSeconds(),\n sss: date.getMilliseconds() / 1000\n };\n } else {\n map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };\n }\n\n forEach(parts, function(part, index) {\n if (index < mapping.length) {\n map[mapping[index]] = +part;\n }\n });\n return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);\n }\n }\n\n return NaN;\n };\n}\n\nfunction createDateInputType(type, regexp, parseDate, format) {\n return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) {\n badInputChecker(scope, element, attr, ctrl);\n baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n var timezone = ctrl && ctrl.$options && ctrl.$options.timezone;\n var previousDate;\n\n ctrl.$$parserName = type;\n ctrl.$parsers.push(function(value) {\n if (ctrl.$isEmpty(value)) return null;\n if (regexp.test(value)) {\n // Note: We cannot read ctrl.$modelValue, as there might be a different\n // parser/formatter in the processing chain so that the model\n // contains some different data format!\n var parsedDate = parseDate(value, previousDate);\n if (timezone === 'UTC') {\n parsedDate.setMinutes(parsedDate.getMinutes() - parsedDate.getTimezoneOffset());\n }\n return parsedDate;\n }\n return undefined;\n });\n\n ctrl.$formatters.push(function(value) {\n if (value && !isDate(value)) {\n throw $ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);\n }\n if (isValidDate(value)) {\n previousDate = value;\n if (previousDate && timezone === 'UTC') {\n var timezoneOffset = 60000 * previousDate.getTimezoneOffset();\n previousDate = new Date(previousDate.getTime() + timezoneOffset);\n }\n return $filter('date')(value, format, timezone);\n } else {\n previousDate = null;\n return '';\n }\n });\n\n if (isDefined(attr.min) || attr.ngMin) {\n var minVal;\n ctrl.$validators.min = function(value) {\n return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal;\n };\n attr.$observe('min', function(val) {\n minVal = parseObservedDateValue(val);\n ctrl.$validate();\n });\n }\n\n if (isDefined(attr.max) || attr.ngMax) {\n var maxVal;\n ctrl.$validators.max = function(value) {\n return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal;\n };\n attr.$observe('max', function(val) {\n maxVal = parseObservedDateValue(val);\n ctrl.$validate();\n });\n }\n\n function isValidDate(value) {\n // Invalid Date: getTime() returns NaN\n return value && !(value.getTime && value.getTime() !== value.getTime());\n }\n\n function parseObservedDateValue(val) {\n return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined;\n }\n };\n}\n\nfunction badInputChecker(scope, element, attr, ctrl) {\n var node = element[0];\n var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity);\n if (nativeValidation) {\n ctrl.$parsers.push(function(value) {\n var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};\n // Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430):\n // - also sets validity.badInput (should only be validity.typeMismatch).\n // - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email)\n // - can ignore this case as we can still read out the erroneous email...\n return validity.badInput && !validity.typeMismatch ? undefined : value;\n });\n }\n}\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n badInputChecker(scope, element, attr, ctrl);\n baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n ctrl.$$parserName = 'number';\n ctrl.$parsers.push(function(value) {\n if (ctrl.$isEmpty(value)) return null;\n if (NUMBER_REGEXP.test(value)) return parseFloat(value);\n return undefined;\n });\n\n ctrl.$formatters.push(function(value) {\n if (!ctrl.$isEmpty(value)) {\n if (!isNumber(value)) {\n throw $ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);\n }\n value = value.toString();\n }\n return value;\n });\n\n if (attr.min || attr.ngMin) {\n var minVal;\n ctrl.$validators.min = function(value) {\n return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;\n };\n\n attr.$observe('min', function(val) {\n if (isDefined(val) && !isNumber(val)) {\n val = parseFloat(val, 10);\n }\n minVal = isNumber(val) && !isNaN(val) ? val : undefined;\n // TODO(matsko): implement validateLater to reduce number of validations\n ctrl.$validate();\n });\n }\n\n if (attr.max || attr.ngMax) {\n var maxVal;\n ctrl.$validators.max = function(value) {\n return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;\n };\n\n attr.$observe('max', function(val) {\n if (isDefined(val) && !isNumber(val)) {\n val = parseFloat(val, 10);\n }\n maxVal = isNumber(val) && !isNaN(val) ? val : undefined;\n // TODO(matsko): implement validateLater to reduce number of validations\n ctrl.$validate();\n });\n }\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n // Note: no badInputChecker here by purpose as `url` is only a validation\n // in browsers, i.e. we can always read out input.value even if it is not valid!\n baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n stringBasedInputType(ctrl);\n\n ctrl.$$parserName = 'url';\n ctrl.$validators.url = function(modelValue, viewValue) {\n var value = modelValue || viewValue;\n return ctrl.$isEmpty(value) || URL_REGEXP.test(value);\n };\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n // Note: no badInputChecker here by purpose as `url` is only a validation\n // in browsers, i.e. we can always read out input.value even if it is not valid!\n baseInputType(scope, element, attr, ctrl, $sniffer, $browser);\n stringBasedInputType(ctrl);\n\n ctrl.$$parserName = 'email';\n ctrl.$validators.email = function(modelValue, viewValue) {\n var value = modelValue || viewValue;\n return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);\n };\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n // make the name unique, if not defined\n if (isUndefined(attr.name)) {\n element.attr('name', nextUid());\n }\n\n var listener = function(ev) {\n if (element[0].checked) {\n ctrl.$setViewValue(attr.value, ev && ev.type);\n }\n };\n\n element.on('click', listener);\n\n ctrl.$render = function() {\n var value = attr.value;\n element[0].checked = (value == ctrl.$viewValue);\n };\n\n attr.$observe('value', ctrl.$render);\n}\n\nfunction parseConstantExpr($parse, context, name, expression, fallback) {\n var parseFn;\n if (isDefined(expression)) {\n parseFn = $parse(expression);\n if (!parseFn.constant) {\n throw minErr('ngModel')('constexpr', 'Expected constant expression for `{0}`, but saw ' +\n '`{1}`.', name, expression);\n }\n return parseFn(context);\n }\n return fallback;\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {\n var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true);\n var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);\n\n var listener = function(ev) {\n ctrl.$setViewValue(element[0].checked, ev && ev.type);\n };\n\n element.on('click', listener);\n\n ctrl.$render = function() {\n element[0].checked = ctrl.$viewValue;\n };\n\n // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false`\n // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert\n // it to a boolean.\n ctrl.$isEmpty = function(value) {\n return value === false;\n };\n\n ctrl.$formatters.push(function(value) {\n return equals(value, trueValue);\n });\n\n ctrl.$parsers.push(function(value) {\n return value ? trueValue : falseValue;\n });\n}\n\n\n/**\n * @ngdoc directive\n * @name textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n * `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n * minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any\n * length.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n * patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n * interaction with the input element.\n * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n */\n\n\n/**\n * @ngdoc directive\n * @name input\n * @restrict E\n *\n * @description\n * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding,\n * input state control, and validation.\n * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers.\n *\n *
\n * **Note:** Not every feature offered is available for all input types.\n * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`.\n *
\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n * minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any\n * length.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n * patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n * interaction with the input element.\n * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n * This parameter is ignored for input[type=password] controls, which will never trim the\n * input.\n *\n * @example\n \n \n \n
\n
\n User name: \n \n Required!
\n Last name: \n \n Too short!\n \n Too long!
\n
\n
\n user = {{user}}
\n myForm.userName.$valid = {{myForm.userName.$valid}}
\n myForm.userName.$error = {{myForm.userName.$error}}
\n myForm.lastName.$valid = {{myForm.lastName.$valid}}
\n myForm.lastName.$error = {{myForm.lastName.$error}}
\n myForm.$valid = {{myForm.$valid}}
\n myForm.$error.required = {{!!myForm.$error.required}}
\n myForm.$error.minlength = {{!!myForm.$error.minlength}}
\n myForm.$error.maxlength = {{!!myForm.$error.maxlength}}
\n
\n
\n \n var user = element(by.exactBinding('user'));\n var userNameValid = element(by.binding('myForm.userName.$valid'));\n var lastNameValid = element(by.binding('myForm.lastName.$valid'));\n var lastNameError = element(by.binding('myForm.lastName.$error'));\n var formValid = element(by.binding('myForm.$valid'));\n var userNameInput = element(by.model('user.name'));\n var userLastInput = element(by.model('user.last'));\n\n it('should initialize to model', function() {\n expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"visitor\"}');\n expect(userNameValid.getText()).toContain('true');\n expect(formValid.getText()).toContain('true');\n });\n\n it('should be invalid if empty when required', function() {\n userNameInput.clear();\n userNameInput.sendKeys('');\n\n expect(user.getText()).toContain('{\"last\":\"visitor\"}');\n expect(userNameValid.getText()).toContain('false');\n expect(formValid.getText()).toContain('false');\n });\n\n it('should be valid if empty when min length is set', function() {\n userLastInput.clear();\n userLastInput.sendKeys('');\n\n expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"\"}');\n expect(lastNameValid.getText()).toContain('true');\n expect(formValid.getText()).toContain('true');\n });\n\n it('should be invalid if less than required min length', function() {\n userLastInput.clear();\n userLastInput.sendKeys('xx');\n\n expect(user.getText()).toContain('{\"name\":\"guest\"}');\n expect(lastNameValid.getText()).toContain('false');\n expect(lastNameError.getText()).toContain('minlength');\n expect(formValid.getText()).toContain('false');\n });\n\n it('should be invalid if longer than max length', function() {\n userLastInput.clear();\n userLastInput.sendKeys('some ridiculously long name');\n\n expect(user.getText()).toContain('{\"name\":\"guest\"}');\n expect(lastNameValid.getText()).toContain('false');\n expect(lastNameError.getText()).toContain('maxlength');\n expect(formValid.getText()).toContain('false');\n });\n \n
\n */\nvar inputDirective = ['$browser', '$sniffer', '$filter', '$parse',\n function($browser, $sniffer, $filter, $parse) {\n return {\n restrict: 'E',\n require: ['?ngModel'],\n link: {\n pre: function(scope, element, attr, ctrls) {\n if (ctrls[0]) {\n (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,\n $browser, $filter, $parse);\n }\n }\n }\n };\n}];\n\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n/**\n * @ngdoc directive\n * @name ngValue\n *\n * @description\n * Binds the given expression to the value of `
\n \n it('should load template defined inside script tag', function() {\n element(by.css('#tpl-link')).click();\n expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);\n });\n \n \n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n return {\n restrict: 'E',\n terminal: true,\n compile: function(element, attr) {\n if (attr.type == 'text/ng-template') {\n var templateUrl = attr.id,\n text = element[0].text;\n\n $templateCache.put(templateUrl, text);\n }\n }\n };\n}];\n\nvar ngOptionsMinErr = minErr('ngOptions');\n/**\n * @ngdoc directive\n * @name select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * The `ngOptions` attribute can be used to dynamically generate a list of `