summaryrefslogtreecommitdiffstats
path: root/third_party/python/jsmin
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/python/jsmin')
-rw-r--r--third_party/python/jsmin/CHANGELOG.txt79
-rw-r--r--third_party/python/jsmin/LICENSE.txt23
-rw-r--r--third_party/python/jsmin/MANIFEST.in1
-rw-r--r--third_party/python/jsmin/PKG-INFO196
-rw-r--r--third_party/python/jsmin/README.rst95
-rw-r--r--third_party/python/jsmin/jsmin.egg-info/PKG-INFO196
-rw-r--r--third_party/python/jsmin/jsmin.egg-info/SOURCES.txt13
-rw-r--r--third_party/python/jsmin/jsmin.egg-info/dependency_links.txt1
-rw-r--r--third_party/python/jsmin/jsmin.egg-info/top_level.txt1
-rw-r--r--third_party/python/jsmin/jsmin/__init__.py252
-rw-r--r--third_party/python/jsmin/jsmin/__main__.py37
-rw-r--r--third_party/python/jsmin/jsmin/test.py644
-rw-r--r--third_party/python/jsmin/setup.cfg5
-rw-r--r--third_party/python/jsmin/setup.py36
14 files changed, 1579 insertions, 0 deletions
diff --git a/third_party/python/jsmin/CHANGELOG.txt b/third_party/python/jsmin/CHANGELOG.txt
new file mode 100644
index 0000000000..1adfa9b9a7
--- /dev/null
+++ b/third_party/python/jsmin/CHANGELOG.txt
@@ -0,0 +1,79 @@
+Changelog
+=========
+
+v3.0.0 (2021-09-08) Ben Bradshaw
+--------------------------------
+
+- Breaking Change: Removed support for Python 2
+
+- Removed usage of use_2to3 in setup.py
+
+v2.2.2 (2017-05-01) Tikitu de Jager
+-----------------------------------
+
+- Add license headers to code files (fixes i#17)
+
+- Remove mercurial files (fixes #20)
+
+v2.2.1 (2016-03-06) Tikitu de Jager
+-----------------------------------
+
+- Fix #14: Infinite loop on `return x / 1;`
+
+v2.2.0 (2015-12-19) Tikitu de Jager
+-----------------------------------
+
+- Merge #13: Preserve "loud comments" starting with `/*!`
+
+ These are commonly used for copyright notices, and are preserved by various
+ other minifiers (e.g. YUI Compressor).
+
+v2.1.6 (2015-10-14) Tikitu de Jager
+-----------------------------------
+
+- Fix #12: Newline following a regex literal should not be elided.
+
+v2.1.5 (2015-10-11) Tikitu de Jager
+-----------------------------------
+
+- Fix #9: Premature end of statement caused by multi-line comment not
+ adding newline.
+
+- Fix #10: Removing multiline comment separating tokens must leave a space.
+
+- Refactor comment handling for maintainability.
+
+v2.1.4 (2015-08-23) Tikitu de Jager
+-----------------------------------
+
+- Fix #6: regex literal matching comment was not correctly matched.
+
+- Refactor regex literal handling for robustness.
+
+v2.1.3 (2015-08-09) Tikitu de Jager
+-----------------------------------
+
+- Reset issue numbering: issues live in github from now on.
+
+- Fix #1: regex literal was not recognised when occurring directly after `{`.
+
+v2.1.2 (2015-07-12) Tikitu de Jager
+-----------------------------------
+
+- Issue numbers here and below refer to the bitbucket repository.
+
+- Fix #17: bug when JS starts with comment then literal regex.
+
+v2.1.1 (2015-02-14) Tikitu de Jager
+-----------------------------------
+
+- Fix #16: bug returning a literal regex containing escaped forward-slashes.
+
+v2.1.0 (2014-12-24) Tikitu de Jager
+-----------------------------------
+
+- First changelog entries; see README.rst for prior contributors.
+
+- Expose quote_chars parameter to provide just enough unofficial Harmony
+ support to be useful.
+
diff --git a/third_party/python/jsmin/LICENSE.txt b/third_party/python/jsmin/LICENSE.txt
new file mode 100644
index 0000000000..193a85326d
--- /dev/null
+++ b/third_party/python/jsmin/LICENSE.txt
@@ -0,0 +1,23 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Dave St.Germain
+
+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/third_party/python/jsmin/MANIFEST.in b/third_party/python/jsmin/MANIFEST.in
new file mode 100644
index 0000000000..ab30e9acee
--- /dev/null
+++ b/third_party/python/jsmin/MANIFEST.in
@@ -0,0 +1 @@
+include *.txt
diff --git a/third_party/python/jsmin/PKG-INFO b/third_party/python/jsmin/PKG-INFO
new file mode 100644
index 0000000000..c4bbd566aa
--- /dev/null
+++ b/third_party/python/jsmin/PKG-INFO
@@ -0,0 +1,196 @@
+Metadata-Version: 1.2
+Name: jsmin
+Version: 3.0.0
+Summary: JavaScript minifier.
+Home-page: https://github.com/tikitu/jsmin/
+Author: Dave St.Germain
+Author-email: dave@st.germa.in
+Maintainer: Tikitu de Jager
+Maintainer-email: tikitu+jsmin@logophile.org
+License: MIT License
+Description: =====
+ jsmin
+ =====
+
+ JavaScript minifier.
+
+ Usage
+ =====
+
+ .. code:: python
+
+ from jsmin import jsmin
+ with open('myfile.js') as js_file:
+ minified = jsmin(js_file.read())
+
+ You can run it as a commandline tool also::
+
+ python -m jsmin myfile.js
+
+ NB: ``jsmin`` makes no attempt to be compatible with
+ `ECMAScript 6 / ES.next / Harmony <http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts>`_.
+ The current maintainer does not intend to add ES6-compatibility. If you would
+ like to take over maintenance and update ``jsmin`` for ES6, please contact
+ `Tikitu de Jager <mailto:tikitu+jsmin@logophile.org>`_. Pull requests are also
+ welcome, of course, but my time to review them is somewhat limited these days.
+
+ If you're using ``jsmin`` on ES6 code, though, you might find the ``quote_chars``
+ parameter useful:
+
+ .. code:: python
+
+ from jsmin import jsmin
+ with open('myfile.js') as js_file:
+ minified = jsmin(js_file.read(), quote_chars="'\"`")
+
+
+ Where to get it
+ ===============
+
+ * install the package `from pypi <https://pypi.python.org/pypi/jsmin/>`_
+ * get the latest release `from latest-release on github <https://github.com/tikitu/jsmin/tree/latest-release/jsmin>`_
+ * get the development version `from master on github <https://github.com/tikitu/jsmin/>`_
+
+
+ Python 2 support removed
+ ========================
+
+ Python 2 support was removed in version 3.0.0. If you need to support Python 2, please use version 2.2.2 with setuptools<58.
+
+ Contributing
+ ============
+
+ `Issues <https://github.com/tikitu/jsmin/issues>`_ and `Pull requests <https://github.com/tikitu/jsmin/pulls>`_
+ will be gratefully received on Github. The project used to be hosted
+ `on bitbucket <https://bitbucket.org/dcs/jsmin/>`_ and old issues can still be
+ found there.
+
+ If possible, please make separate pull requests for tests and for code: tests will be added to the `latest-release` branch while code will go to `master`.
+
+ Unless you request otherwise, your Github identity will be added to the contributor's list below; if you prefer a
+ different name feel free to add it in your pull request instead. (If you prefer not to be mentioned you'll have to let
+ the maintainer know somehow.)
+
+ Build/test status
+ =================
+
+ Both branches are tested with Travis: https://travis-ci.org/tikitu/jsmin
+
+ The `latest-release` branch (the version on PyPI plus any new tests) is tested against CPython 3.
+ Currently:
+
+ .. image:: https://travis-ci.org/tikitu/jsmin.png?branch=latest-release
+
+ If that branch is failing that means there's a new test that fails on *the latest released version on pypi*, with no fix yet
+ released.
+
+ The `master` branch (development version, might be ahead of latest released version) is tested against CPython 3.
+ Currently:
+
+ .. image:: https://travis-ci.org/tikitu/jsmin.png?branch=master
+
+ If `master` is failing don't use it, but as long as `latest-release` is passing the pypi release should be ok.
+
+ Contributors (chronological commit order)
+ =========================================
+
+ * `Dave St.Germain <https://bitbucket.org/dcs>`_ (original author)
+ * `Hans weltar <https://bitbucket.org/hansweltar>`_
+ * `Tikitu de Jager <mailto:tikitu+jsmin@logophile.org>`_ (current maintainer)
+ * https://bitbucket.org/rennat
+ * `Nick Alexander <https://bitbucket.org/ncalexan>`_
+ * `Gennady Kovshenin <https://github.com/soulseekah>`_
+ * `Matt Molyneaux <https://github.com/moggers87>`_
+ * `Albert Wang <https://github.com/albertyw>`_
+ * `Ben Bradshaw <https://github.com/serenecloud>`_
+
+ Changelog
+ =========
+
+ v3.0.0 (2021-09-08) Ben Bradshaw
+ --------------------------------
+
+ - Breaking Change: Removed support for Python 2
+
+ - Removed usage of use_2to3 in setup.py
+
+ v2.2.2 (2017-05-01) Tikitu de Jager
+ -----------------------------------
+
+ - Add license headers to code files (fixes i#17)
+
+ - Remove mercurial files (fixes #20)
+
+ v2.2.1 (2016-03-06) Tikitu de Jager
+ -----------------------------------
+
+ - Fix #14: Infinite loop on `return x / 1;`
+
+ v2.2.0 (2015-12-19) Tikitu de Jager
+ -----------------------------------
+
+ - Merge #13: Preserve "loud comments" starting with `/*!`
+
+ These are commonly used for copyright notices, and are preserved by various
+ other minifiers (e.g. YUI Compressor).
+
+ v2.1.6 (2015-10-14) Tikitu de Jager
+ -----------------------------------
+
+ - Fix #12: Newline following a regex literal should not be elided.
+
+ v2.1.5 (2015-10-11) Tikitu de Jager
+ -----------------------------------
+
+ - Fix #9: Premature end of statement caused by multi-line comment not
+ adding newline.
+
+ - Fix #10: Removing multiline comment separating tokens must leave a space.
+
+ - Refactor comment handling for maintainability.
+
+ v2.1.4 (2015-08-23) Tikitu de Jager
+ -----------------------------------
+
+ - Fix #6: regex literal matching comment was not correctly matched.
+
+ - Refactor regex literal handling for robustness.
+
+ v2.1.3 (2015-08-09) Tikitu de Jager
+ -----------------------------------
+
+ - Reset issue numbering: issues live in github from now on.
+
+ - Fix #1: regex literal was not recognised when occurring directly after `{`.
+
+ v2.1.2 (2015-07-12) Tikitu de Jager
+ -----------------------------------
+
+ - Issue numbers here and below refer to the bitbucket repository.
+
+ - Fix #17: bug when JS starts with comment then literal regex.
+
+ v2.1.1 (2015-02-14) Tikitu de Jager
+ -----------------------------------
+
+ - Fix #16: bug returning a literal regex containing escaped forward-slashes.
+
+ v2.1.0 (2014-12-24) Tikitu de Jager
+ -----------------------------------
+
+ - First changelog entries; see README.rst for prior contributors.
+
+ - Expose quote_chars parameter to provide just enough unofficial Harmony
+ support to be useful.
+
+
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Web Environment
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
+Classifier: Topic :: Software Development :: Pre-processors
+Classifier: Topic :: Text Processing :: Filters
diff --git a/third_party/python/jsmin/README.rst b/third_party/python/jsmin/README.rst
new file mode 100644
index 0000000000..8f6a9bdec5
--- /dev/null
+++ b/third_party/python/jsmin/README.rst
@@ -0,0 +1,95 @@
+=====
+jsmin
+=====
+
+JavaScript minifier.
+
+Usage
+=====
+
+.. code:: python
+
+ from jsmin import jsmin
+ with open('myfile.js') as js_file:
+ minified = jsmin(js_file.read())
+
+You can run it as a commandline tool also::
+
+ python -m jsmin myfile.js
+
+NB: ``jsmin`` makes no attempt to be compatible with
+`ECMAScript 6 / ES.next / Harmony <http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts>`_.
+The current maintainer does not intend to add ES6-compatibility. If you would
+like to take over maintenance and update ``jsmin`` for ES6, please contact
+`Tikitu de Jager <mailto:tikitu+jsmin@logophile.org>`_. Pull requests are also
+welcome, of course, but my time to review them is somewhat limited these days.
+
+If you're using ``jsmin`` on ES6 code, though, you might find the ``quote_chars``
+parameter useful:
+
+.. code:: python
+
+ from jsmin import jsmin
+ with open('myfile.js') as js_file:
+ minified = jsmin(js_file.read(), quote_chars="'\"`")
+
+
+Where to get it
+===============
+
+* install the package `from pypi <https://pypi.python.org/pypi/jsmin/>`_
+* get the latest release `from latest-release on github <https://github.com/tikitu/jsmin/tree/latest-release/jsmin>`_
+* get the development version `from master on github <https://github.com/tikitu/jsmin/>`_
+
+
+Python 2 support removed
+========================
+
+Python 2 support was removed in version 3.0.0. If you need to support Python 2, please use version 2.2.2 with setuptools<58.
+
+Contributing
+============
+
+`Issues <https://github.com/tikitu/jsmin/issues>`_ and `Pull requests <https://github.com/tikitu/jsmin/pulls>`_
+will be gratefully received on Github. The project used to be hosted
+`on bitbucket <https://bitbucket.org/dcs/jsmin/>`_ and old issues can still be
+found there.
+
+If possible, please make separate pull requests for tests and for code: tests will be added to the `latest-release` branch while code will go to `master`.
+
+Unless you request otherwise, your Github identity will be added to the contributor's list below; if you prefer a
+different name feel free to add it in your pull request instead. (If you prefer not to be mentioned you'll have to let
+the maintainer know somehow.)
+
+Build/test status
+=================
+
+Both branches are tested with Travis: https://travis-ci.org/tikitu/jsmin
+
+The `latest-release` branch (the version on PyPI plus any new tests) is tested against CPython 3.
+Currently:
+
+.. image:: https://travis-ci.org/tikitu/jsmin.png?branch=latest-release
+
+If that branch is failing that means there's a new test that fails on *the latest released version on pypi*, with no fix yet
+released.
+
+The `master` branch (development version, might be ahead of latest released version) is tested against CPython 3.
+Currently:
+
+.. image:: https://travis-ci.org/tikitu/jsmin.png?branch=master
+
+If `master` is failing don't use it, but as long as `latest-release` is passing the pypi release should be ok.
+
+Contributors (chronological commit order)
+=========================================
+
+* `Dave St.Germain <https://bitbucket.org/dcs>`_ (original author)
+* `Hans weltar <https://bitbucket.org/hansweltar>`_
+* `Tikitu de Jager <mailto:tikitu+jsmin@logophile.org>`_ (current maintainer)
+* https://bitbucket.org/rennat
+* `Nick Alexander <https://bitbucket.org/ncalexan>`_
+* `Gennady Kovshenin <https://github.com/soulseekah>`_
+* `Matt Molyneaux <https://github.com/moggers87>`_
+* `Albert Wang <https://github.com/albertyw>`_
+* `Ben Bradshaw <https://github.com/serenecloud>`_
diff --git a/third_party/python/jsmin/jsmin.egg-info/PKG-INFO b/third_party/python/jsmin/jsmin.egg-info/PKG-INFO
new file mode 100644
index 0000000000..c4bbd566aa
--- /dev/null
+++ b/third_party/python/jsmin/jsmin.egg-info/PKG-INFO
@@ -0,0 +1,196 @@
+Metadata-Version: 1.2
+Name: jsmin
+Version: 3.0.0
+Summary: JavaScript minifier.
+Home-page: https://github.com/tikitu/jsmin/
+Author: Dave St.Germain
+Author-email: dave@st.germa.in
+Maintainer: Tikitu de Jager
+Maintainer-email: tikitu+jsmin@logophile.org
+License: MIT License
+Description: =====
+ jsmin
+ =====
+
+ JavaScript minifier.
+
+ Usage
+ =====
+
+ .. code:: python
+
+ from jsmin import jsmin
+ with open('myfile.js') as js_file:
+ minified = jsmin(js_file.read())
+
+ You can run it as a commandline tool also::
+
+ python -m jsmin myfile.js
+
+ NB: ``jsmin`` makes no attempt to be compatible with
+ `ECMAScript 6 / ES.next / Harmony <http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts>`_.
+ The current maintainer does not intend to add ES6-compatibility. If you would
+ like to take over maintenance and update ``jsmin`` for ES6, please contact
+ `Tikitu de Jager <mailto:tikitu+jsmin@logophile.org>`_. Pull requests are also
+ welcome, of course, but my time to review them is somewhat limited these days.
+
+ If you're using ``jsmin`` on ES6 code, though, you might find the ``quote_chars``
+ parameter useful:
+
+ .. code:: python
+
+ from jsmin import jsmin
+ with open('myfile.js') as js_file:
+ minified = jsmin(js_file.read(), quote_chars="'\"`")
+
+
+ Where to get it
+ ===============
+
+ * install the package `from pypi <https://pypi.python.org/pypi/jsmin/>`_
+ * get the latest release `from latest-release on github <https://github.com/tikitu/jsmin/tree/latest-release/jsmin>`_
+ * get the development version `from master on github <https://github.com/tikitu/jsmin/>`_
+
+
+ Python 2 support removed
+ ========================
+
+ Python 2 support was removed in version 3.0.0. If you need to support Python 2, please use version 2.2.2 with setuptools<58.
+
+ Contributing
+ ============
+
+ `Issues <https://github.com/tikitu/jsmin/issues>`_ and `Pull requests <https://github.com/tikitu/jsmin/pulls>`_
+ will be gratefully received on Github. The project used to be hosted
+ `on bitbucket <https://bitbucket.org/dcs/jsmin/>`_ and old issues can still be
+ found there.
+
+ If possible, please make separate pull requests for tests and for code: tests will be added to the `latest-release` branch while code will go to `master`.
+
+ Unless you request otherwise, your Github identity will be added to the contributor's list below; if you prefer a
+ different name feel free to add it in your pull request instead. (If you prefer not to be mentioned you'll have to let
+ the maintainer know somehow.)
+
+ Build/test status
+ =================
+
+ Both branches are tested with Travis: https://travis-ci.org/tikitu/jsmin
+
+ The `latest-release` branch (the version on PyPI plus any new tests) is tested against CPython 3.
+ Currently:
+
+ .. image:: https://travis-ci.org/tikitu/jsmin.png?branch=latest-release
+
+ If that branch is failing that means there's a new test that fails on *the latest released version on pypi*, with no fix yet
+ released.
+
+ The `master` branch (development version, might be ahead of latest released version) is tested against CPython 3.
+ Currently:
+
+ .. image:: https://travis-ci.org/tikitu/jsmin.png?branch=master
+
+ If `master` is failing don't use it, but as long as `latest-release` is passing the pypi release should be ok.
+
+ Contributors (chronological commit order)
+ =========================================
+
+ * `Dave St.Germain <https://bitbucket.org/dcs>`_ (original author)
+ * `Hans weltar <https://bitbucket.org/hansweltar>`_
+ * `Tikitu de Jager <mailto:tikitu+jsmin@logophile.org>`_ (current maintainer)
+ * https://bitbucket.org/rennat
+ * `Nick Alexander <https://bitbucket.org/ncalexan>`_
+ * `Gennady Kovshenin <https://github.com/soulseekah>`_
+ * `Matt Molyneaux <https://github.com/moggers87>`_
+ * `Albert Wang <https://github.com/albertyw>`_
+ * `Ben Bradshaw <https://github.com/serenecloud>`_
+
+ Changelog
+ =========
+
+ v3.0.0 (2021-09-08) Ben Bradshaw
+ --------------------------------
+
+ - Breaking Change: Removed support for Python 2
+
+ - Removed usage of use_2to3 in setup.py
+
+ v2.2.2 (2017-05-01) Tikitu de Jager
+ -----------------------------------
+
+ - Add license headers to code files (fixes i#17)
+
+ - Remove mercurial files (fixes #20)
+
+ v2.2.1 (2016-03-06) Tikitu de Jager
+ -----------------------------------
+
+ - Fix #14: Infinite loop on `return x / 1;`
+
+ v2.2.0 (2015-12-19) Tikitu de Jager
+ -----------------------------------
+
+ - Merge #13: Preserve "loud comments" starting with `/*!`
+
+ These are commonly used for copyright notices, and are preserved by various
+ other minifiers (e.g. YUI Compressor).
+
+ v2.1.6 (2015-10-14) Tikitu de Jager
+ -----------------------------------
+
+ - Fix #12: Newline following a regex literal should not be elided.
+
+ v2.1.5 (2015-10-11) Tikitu de Jager
+ -----------------------------------
+
+ - Fix #9: Premature end of statement caused by multi-line comment not
+ adding newline.
+
+ - Fix #10: Removing multiline comment separating tokens must leave a space.
+
+ - Refactor comment handling for maintainability.
+
+ v2.1.4 (2015-08-23) Tikitu de Jager
+ -----------------------------------
+
+ - Fix #6: regex literal matching comment was not correctly matched.
+
+ - Refactor regex literal handling for robustness.
+
+ v2.1.3 (2015-08-09) Tikitu de Jager
+ -----------------------------------
+
+ - Reset issue numbering: issues live in github from now on.
+
+ - Fix #1: regex literal was not recognised when occurring directly after `{`.
+
+ v2.1.2 (2015-07-12) Tikitu de Jager
+ -----------------------------------
+
+ - Issue numbers here and below refer to the bitbucket repository.
+
+ - Fix #17: bug when JS starts with comment then literal regex.
+
+ v2.1.1 (2015-02-14) Tikitu de Jager
+ -----------------------------------
+
+ - Fix #16: bug returning a literal regex containing escaped forward-slashes.
+
+ v2.1.0 (2014-12-24) Tikitu de Jager
+ -----------------------------------
+
+ - First changelog entries; see README.rst for prior contributors.
+
+ - Expose quote_chars parameter to provide just enough unofficial Harmony
+ support to be useful.
+
+
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Web Environment
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
+Classifier: Topic :: Software Development :: Pre-processors
+Classifier: Topic :: Text Processing :: Filters
diff --git a/third_party/python/jsmin/jsmin.egg-info/SOURCES.txt b/third_party/python/jsmin/jsmin.egg-info/SOURCES.txt
new file mode 100644
index 0000000000..ae208f4b60
--- /dev/null
+++ b/third_party/python/jsmin/jsmin.egg-info/SOURCES.txt
@@ -0,0 +1,13 @@
+CHANGELOG.txt
+LICENSE.txt
+MANIFEST.in
+README.rst
+setup.cfg
+setup.py
+jsmin/__init__.py
+jsmin/__main__.py
+jsmin/test.py
+jsmin.egg-info/PKG-INFO
+jsmin.egg-info/SOURCES.txt
+jsmin.egg-info/dependency_links.txt
+jsmin.egg-info/top_level.txt \ No newline at end of file
diff --git a/third_party/python/jsmin/jsmin.egg-info/dependency_links.txt b/third_party/python/jsmin/jsmin.egg-info/dependency_links.txt
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/third_party/python/jsmin/jsmin.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/third_party/python/jsmin/jsmin.egg-info/top_level.txt b/third_party/python/jsmin/jsmin.egg-info/top_level.txt
new file mode 100644
index 0000000000..79abaa99ee
--- /dev/null
+++ b/third_party/python/jsmin/jsmin.egg-info/top_level.txt
@@ -0,0 +1 @@
+jsmin
diff --git a/third_party/python/jsmin/jsmin/__init__.py b/third_party/python/jsmin/jsmin/__init__.py
new file mode 100644
index 0000000000..c906d14a03
--- /dev/null
+++ b/third_party/python/jsmin/jsmin/__init__.py
@@ -0,0 +1,252 @@
+# vim: set fileencoding=utf-8 :
+
+# This code is original from jsmin by Douglas Crockford, it was translated to
+# Python by Baruch Even. It was rewritten by Dave St.Germain for speed.
+#
+# The MIT License (MIT)
+#
+# Copyright (c) 2013 Dave St.Germain
+#
+# 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.
+
+
+import io
+
+__all__ = ['jsmin', 'JavascriptMinify']
+__version__ = '3.0.0'
+
+
+def jsmin(js, **kwargs):
+ """
+ returns a minified version of the javascript string
+ """
+ klass = io.StringIO
+ ins = klass(js)
+ outs = klass()
+ JavascriptMinify(ins, outs, **kwargs).minify()
+ return outs.getvalue()
+
+
+class JavascriptMinify(object):
+ """
+ Minify an input stream of javascript, writing
+ to an output stream
+ """
+
+ def __init__(self, instream=None, outstream=None, quote_chars="'\""):
+ self.ins = instream
+ self.outs = outstream
+ self.quote_chars = quote_chars
+
+ def minify(self, instream=None, outstream=None):
+ if instream and outstream:
+ self.ins, self.outs = instream, outstream
+
+ self.is_return = False
+ self.return_buf = ''
+
+ def write(char):
+ # all of this is to support literal regular expressions.
+ # sigh
+ if char in 'return':
+ self.return_buf += char
+ self.is_return = self.return_buf == 'return'
+ else:
+ self.return_buf = ''
+ self.is_return = self.is_return and char < '!'
+ self.outs.write(char)
+ if self.is_return:
+ self.return_buf = ''
+
+ read = self.ins.read
+
+ space_strings = "abcdefghijklmnopqrstuvwxyz"\
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$\\"
+ self.space_strings = space_strings
+ starters, enders = '{[(+-', '}])+-/' + self.quote_chars
+ newlinestart_strings = starters + space_strings + self.quote_chars
+ newlineend_strings = enders + space_strings + self.quote_chars
+ self.newlinestart_strings = newlinestart_strings
+ self.newlineend_strings = newlineend_strings
+
+ do_newline = False
+ do_space = False
+ escape_slash_count = 0
+ in_quote = ''
+ quote_buf = []
+
+ previous = ';'
+ previous_non_space = ';'
+ next1 = read(1)
+
+ while next1:
+ next2 = read(1)
+ if in_quote:
+ quote_buf.append(next1)
+
+ if next1 == in_quote:
+ numslashes = 0
+ for c in reversed(quote_buf[:-1]):
+ if c != '\\':
+ break
+ else:
+ numslashes += 1
+ if numslashes % 2 == 0:
+ in_quote = ''
+ write(''.join(quote_buf))
+ elif next1 in '\r\n':
+ next2, do_newline = self.newline(
+ previous_non_space, next2, do_newline)
+ elif next1 < '!':
+ if (previous_non_space in space_strings \
+ or previous_non_space > '~') \
+ and (next2 in space_strings or next2 > '~'):
+ do_space = True
+ elif previous_non_space in '-+' and next2 == previous_non_space:
+ # protect against + ++ or - -- sequences
+ do_space = True
+ elif self.is_return and next2 == '/':
+ # returning a regex...
+ write(' ')
+ elif next1 == '/':
+ if do_space:
+ write(' ')
+ if next2 == '/':
+ # Line comment: treat it as a newline, but skip it
+ next2 = self.line_comment(next1, next2)
+ next1 = '\n'
+ next2, do_newline = self.newline(
+ previous_non_space, next2, do_newline)
+ elif next2 == '*':
+ self.block_comment(next1, next2)
+ next2 = read(1)
+ if previous_non_space in space_strings:
+ do_space = True
+ next1 = previous
+ else:
+ if previous_non_space in '{(,=:[?!&|;' or self.is_return:
+ self.regex_literal(next1, next2)
+ # hackish: after regex literal next1 is still /
+ # (it was the initial /, now it's the last /)
+ next2 = read(1)
+ else:
+ write('/')
+ else:
+ if do_newline:
+ write('\n')
+ do_newline = False
+ do_space = False
+ if do_space:
+ do_space = False
+ write(' ')
+
+ write(next1)
+ if next1 in self.quote_chars:
+ in_quote = next1
+ quote_buf = []
+
+ if next1 >= '!':
+ previous_non_space = next1
+
+ if next1 == '\\':
+ escape_slash_count += 1
+ else:
+ escape_slash_count = 0
+
+ previous = next1
+ next1 = next2
+
+ def regex_literal(self, next1, next2):
+ assert next1 == '/' # otherwise we should not be called!
+
+ self.return_buf = ''
+
+ read = self.ins.read
+ write = self.outs.write
+
+ in_char_class = False
+
+ write('/')
+
+ next = next2
+ while next and (next != '/' or in_char_class):
+ write(next)
+ if next == '\\':
+ write(read(1)) # whatever is next is escaped
+ elif next == '[':
+ write(read(1)) # character class cannot be empty
+ in_char_class = True
+ elif next == ']':
+ in_char_class = False
+ next = read(1)
+
+ write('/')
+
+ def line_comment(self, next1, next2):
+ assert next1 == next2 == '/'
+
+ read = self.ins.read
+
+ while next1 and next1 not in '\r\n':
+ next1 = read(1)
+ while next1 and next1 in '\r\n':
+ next1 = read(1)
+
+ return next1
+
+ def block_comment(self, next1, next2):
+ assert next1 == '/'
+ assert next2 == '*'
+
+ read = self.ins.read
+
+ # Skip past first /* and avoid catching on /*/...*/
+ next1 = read(1)
+ next2 = read(1)
+
+ comment_buffer = '/*'
+ while next1 != '*' or next2 != '/':
+ comment_buffer += next1
+ next1 = next2
+ next2 = read(1)
+
+ if comment_buffer.startswith("/*!"):
+ # comment needs preserving
+ self.outs.write(comment_buffer)
+ self.outs.write("*/\n")
+
+
+ def newline(self, previous_non_space, next2, do_newline):
+ read = self.ins.read
+
+ if previous_non_space and (
+ previous_non_space in self.newlineend_strings
+ or previous_non_space > '~'):
+ while 1:
+ if next2 < '!':
+ next2 = read(1)
+ if not next2:
+ break
+ else:
+ if next2 in self.newlinestart_strings \
+ or next2 > '~' or next2 == '/':
+ do_newline = True
+ break
+
+ return next2, do_newline
diff --git a/third_party/python/jsmin/jsmin/__main__.py b/third_party/python/jsmin/jsmin/__main__.py
new file mode 100644
index 0000000000..6d37a3eb7b
--- /dev/null
+++ b/third_party/python/jsmin/jsmin/__main__.py
@@ -0,0 +1,37 @@
+# vim: set fileencoding=utf-8 :
+
+# This code is original from jsmin by Douglas Crockford, it was translated to
+# Python by Baruch Even. It was rewritten by Dave St.Germain for speed.
+#
+# The MIT License (MIT)
+#·
+# Copyright (c) 2013 Dave St.Germain
+#·
+# 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.
+
+import sys, os, glob
+from jsmin import JavascriptMinify
+
+for f in sys.argv[1:]:
+ with open(f, 'r') as js:
+ minifier = JavascriptMinify(js, sys.stdout)
+ minifier.minify()
+ sys.stdout.write('\n')
+
+
diff --git a/third_party/python/jsmin/jsmin/test.py b/third_party/python/jsmin/jsmin/test.py
new file mode 100644
index 0000000000..74fbaadeae
--- /dev/null
+++ b/third_party/python/jsmin/jsmin/test.py
@@ -0,0 +1,644 @@
+# vim: set fileencoding=utf-8 :
+
+# This code is original from jsmin by Douglas Crockford, it was translated to
+# Python by Baruch Even. It was rewritten by Dave St.Germain for speed.
+#
+# The MIT License (MIT)
+#·
+# Copyright (c) 2013 Dave St.Germain
+#·
+# 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.
+
+import unittest
+import jsmin
+
+
+class JsTests(unittest.TestCase):
+ def _minify(self, js):
+ return jsmin.jsmin(js)
+
+ def assertEqual(self, thing1, thing2):
+ if thing1 != thing2:
+ print(repr(thing1), repr(thing2))
+ raise AssertionError
+ return True
+
+ def assertMinified(self, js_input, expected, **kwargs):
+ minified = jsmin.jsmin(js_input, **kwargs)
+ assert minified == expected, "\ngot: %r\nexp: %r" % (minified, expected)
+
+ def testQuoted(self):
+ js = r'''
+ Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+ });
+
+ '''
+ expected = r"""Object.extend(String,{interpret:function(value){return value==null?'':String(value);},specialChar:{'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','\\':'\\\\'}});"""
+ self.assertMinified(js, expected)
+
+ def testSingleComment(self):
+ js = r'''// use native browser JS 1.6 implementation if available
+ if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+ if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+
+ // hey there
+ function() {// testing comment
+ foo;
+ //something something
+
+ location = 'http://foo.com;'; // goodbye
+ }
+ //bye
+ '''
+ expected = r"""if(Object.isFunction(Array.prototype.forEach))
+Array.prototype._each=Array.prototype.forEach;if(!Array.prototype.indexOf)Array.prototype.indexOf=function(item,i){function(){foo;location='http://foo.com;';}"""
+ self.assertMinified(js, expected)
+
+ def testEmpty(self):
+ self.assertMinified('', '')
+ self.assertMinified(' ', '')
+ self.assertMinified('\n', '')
+ self.assertMinified('\r\n', '')
+ self.assertMinified('\t', '')
+
+
+ def testMultiComment(self):
+ js = r"""
+ function foo() {
+ print('hey');
+ }
+ /*
+ if(this.options.zindex) {
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ this.element.style.zIndex = this.options.zindex;
+ }
+ */
+ another thing;
+ """
+ expected = r"""function foo(){print('hey');}
+another thing;"""
+ self.assertMinified(js, expected)
+
+ def testLeadingComment(self):
+ js = r"""/* here is a comment at the top
+
+ it ends here */
+ function foo() {
+ alert('crud');
+ }
+
+ """
+ expected = r"""function foo(){alert('crud');}"""
+ self.assertMinified(js, expected)
+
+ def testBlockCommentStartingWithSlash(self):
+ self.assertMinified('A; /*/ comment */ B', 'A;B')
+
+ def testBlockCommentEndingWithSlash(self):
+ self.assertMinified('A; /* comment /*/ B', 'A;B')
+
+ def testLeadingBlockCommentStartingWithSlash(self):
+ self.assertMinified('/*/ comment */ A', 'A')
+
+ def testLeadingBlockCommentEndingWithSlash(self):
+ self.assertMinified('/* comment /*/ A', 'A')
+
+ def testEmptyBlockComment(self):
+ self.assertMinified('/**/ A', 'A')
+
+ def testBlockCommentMultipleOpen(self):
+ self.assertMinified('/* A /* B */ C', 'C')
+
+ def testJustAComment(self):
+ self.assertMinified(' // a comment', '')
+
+ def test_issue_bitbucket_10(self):
+ js = '''
+ files = [{name: value.replace(/^.*\\\\/, '')}];
+ // comment
+ A
+ '''
+ expected = '''files=[{name:value.replace(/^.*\\\\/,'')}];A'''
+ self.assertMinified(js, expected)
+
+ def test_issue_bitbucket_10_without_semicolon(self):
+ js = '''
+ files = [{name: value.replace(/^.*\\\\/, '')}]
+ // comment
+ A
+ '''
+ expected = '''files=[{name:value.replace(/^.*\\\\/,'')}]\nA'''
+ self.assertMinified(js, expected)
+
+ def testRe(self):
+ js = r'''
+ var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ });'''
+ expected = r"""var str=this.replace(/\\./g,'@').replace(/"[^"\\\n\r]*"/g,'');return(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);});"""
+ self.assertMinified(js, expected)
+
+ def testIgnoreComment(self):
+ js = r"""
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ tree: options.tree,
+ hoverclass: options.hoverclass,
+ onHover: Sortable.onHover
+ }
+
+ var options_for_tree = {
+ onHover: Sortable.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass
+ }
+
+ // fix for gecko engine
+ Element.cleanWhitespace(element);
+ """
+ expected = r"""var options_for_droppable={overlap:options.overlap,containment:options.containment,tree:options.tree,hoverclass:options.hoverclass,onHover:Sortable.onHover}
+var options_for_tree={onHover:Sortable.onEmptyHover,overlap:options.overlap,containment:options.containment,hoverclass:options.hoverclass}
+Element.cleanWhitespace(element);"""
+ self.assertMinified(js, expected)
+
+ def testHairyRe(self):
+ js = r"""
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+ """
+ expected = r"""inspect:function(useDoubleQuotes){var escapedString=this.gsub(/[\x00-\x1f\\]/,function(match){var character=String.specialChar[match[0]];return character?character:'\\u00'+match[0].charCodeAt().toPaddedString(2,16);});if(useDoubleQuotes)return'"'+escapedString.replace(/"/g,'\\"')+'"';return"'"+escapedString.replace(/'/g,'\\\'')+"'";},toJSON:function(){return this.inspect(true);},unfilterJSON:function(filter){return this.sub(filter||Prototype.JSONFilter,'#{1}');},"""
+ self.assertMinified(js, expected)
+
+ def testLiteralRe(self):
+ js = r"""
+ myString.replace(/\\/g, '/');
+ console.log("hi");
+ """
+ expected = r"""myString.replace(/\\/g,'/');console.log("hi");"""
+ self.assertMinified(js, expected)
+
+ js = r''' return /^data:image\//i.test(url) ||
+ /^(https?|ftp|file|about|chrome|resource):/.test(url);
+ '''
+ expected = r'''return /^data:image\//i.test(url)||/^(https?|ftp|file|about|chrome|resource):/.test(url);'''
+ self.assertMinified(js, expected)
+
+ def testNoBracesWithComment(self):
+ js = r"""
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ """
+ expected = r"""onSuccess:function(transport){var js=transport.responseText.strip();if(!/^\[.*\]$/.test(js))
+throw'Server returned an invalid collection representation.';this._collection=eval(js);this.checkForExternalText();}.bind(this),onFailure:this.onFailure});"""
+ self.assertMinified(js, expected)
+ js_without_comment = r"""
+ onSuccess: function(transport) {
+ var js = transport.responseText.strip();
+ if (!/^\[.*\]$/.test(js))
+ throw 'Server returned an invalid collection representation.';
+ this._collection = eval(js);
+ this.checkForExternalText();
+ }.bind(this),
+ onFailure: this.onFailure
+ });
+ """
+ self.assertMinified(js_without_comment, expected)
+
+ def testSpaceInRe(self):
+ js = r"""
+ num = num.replace(/ /g,'');
+ """
+ self.assertMinified(js, "num=num.replace(/ /g,'');")
+
+ def testEmptyString(self):
+ js = r'''
+ function foo('') {
+
+ }
+ '''
+ self.assertMinified(js, "function foo(''){}")
+
+ def testDoubleSpace(self):
+ js = r'''
+var foo = "hey";
+ '''
+ self.assertMinified(js, 'var foo="hey";')
+
+ def testLeadingRegex(self):
+ js = r'/[d]+/g '
+ self.assertMinified(js, js.strip())
+
+ def testLeadingString(self):
+ js = r"'a string in the middle of nowhere'; // and a comment"
+ self.assertMinified(js, "'a string in the middle of nowhere';")
+
+ def testSingleCommentEnd(self):
+ js = r'// a comment\n'
+ self.assertMinified(js, '')
+
+ def testInputStream(self):
+ try:
+ from StringIO import StringIO
+ except ImportError:
+ from io import StringIO
+
+ ins = StringIO(r'''
+ function foo('') {
+
+ }
+ ''')
+ outs = StringIO()
+ m = jsmin.JavascriptMinify()
+ m.minify(ins, outs)
+ output = outs.getvalue()
+ assert output == "function foo(''){}"
+
+ def testUnicode(self):
+ instr = u'\u4000 //foo'
+ expected = u'\u4000'
+ output = jsmin.jsmin(instr)
+ self.assertEqual(output, expected)
+
+ def testCommentBeforeEOF(self):
+ self.assertMinified("//test\r\n", "")
+
+ def testCommentInObj(self):
+ self.assertMinified("""{
+ a: 1,//comment
+ }""", "{a:1,}")
+
+ def testCommentInObj2(self):
+ self.assertMinified("{a: 1//comment\r\n}", "{a:1}")
+
+ def testImplicitSemicolon(self):
+ # return \n 1 is equivalent with return; 1
+ # so best make sure jsmin retains the newline
+ self.assertMinified("return\na", "return\na")
+
+ def test_explicit_semicolon(self):
+ self.assertMinified("return;//comment\r\na", "return;a")
+
+ def testImplicitSemicolon2(self):
+ self.assertMinified("return//comment...\r\nar", "return\nar")
+
+ def testImplicitSemicolon3(self):
+ self.assertMinified("return//comment...\r\na", "return\na")
+
+ def testSingleComment2(self):
+ self.assertMinified('x.replace(/\//, "_")// slash to underscore',
+ 'x.replace(/\//,"_")')
+
+ def testSlashesNearComments(self):
+ original = '''
+ { a: n / 2, }
+ // comment
+ '''
+ expected = '''{a:n/2,}'''
+ self.assertMinified(original, expected)
+
+ def testReturn(self):
+ original = '''
+ return foo;//comment
+ return bar;'''
+ expected = 'return foo;return bar;'
+ self.assertMinified(original, expected)
+ original = '''
+ return foo
+ return bar;'''
+ expected = 'return foo\nreturn bar;'
+ self.assertMinified(original, expected)
+
+ def test_space_plus(self):
+ original = '"s" + ++e + "s"'
+ expected = '"s"+ ++e+"s"'
+ self.assertMinified(original, expected)
+
+ def test_no_final_newline(self):
+ original = '"s"'
+ expected = '"s"'
+ self.assertMinified(original, expected)
+
+ def test_space_with_regex_repeats(self):
+ original = '/(NaN| {2}|^$)/.test(a)&&(a="M 0 0");'
+ self.assertMinified(original, original) # there should be nothing jsmin can do here
+
+ def test_space_with_regex_repeats_not_at_start(self):
+ original = 'aaa;/(NaN| {2}|^$)/.test(a)&&(a="M 0 0");'
+ self.assertMinified(original, original) # there should be nothing jsmin can do here
+
+ def test_space_in_regex(self):
+ original = '/a (a)/.test("a")'
+ self.assertMinified(original, original)
+
+ def test_brackets_around_slashed_regex(self):
+ original = 'function a() { /\//.test("a") }'
+ expected = 'function a(){/\//.test("a")}'
+ self.assertMinified(original, expected)
+
+ def test_angular_1(self):
+ original = '''var /** holds major version number for IE or NaN for real browsers */
+ msie,
+ jqLite, // delay binding since jQuery could be loaded after us.'''
+ minified = jsmin.jsmin(original)
+ self.assertTrue('var\nmsie' in minified)
+
+ def test_angular_2(self):
+ original = 'var/* comment */msie;'
+ expected = 'var msie;'
+ self.assertMinified(original, expected)
+
+ def test_angular_3(self):
+ original = 'var /* comment */msie;'
+ expected = 'var msie;'
+ self.assertMinified(original, expected)
+
+ def test_angular_4(self):
+ original = 'var /* comment */ msie;'
+ expected = 'var msie;'
+ self.assertMinified(original, expected)
+
+ def test_angular_5(self):
+ original = 'a/b'
+ self.assertMinified(original, original)
+
+ def testBackticks(self):
+ original = '`test`'
+ self.assertMinified(original, original, quote_chars="'\"`")
+
+ original = '` test with leading whitespace`'
+ self.assertMinified(original, original, quote_chars="'\"`")
+
+ original = '`test with trailing whitespace `'
+ self.assertMinified(original, original, quote_chars="'\"`")
+
+ original = '''`test
+with a new line`'''
+ self.assertMinified(original, original, quote_chars="'\"`")
+
+ original = '''dumpAvStats: function(stats) {
+ var statsString = "";
+ if (stats.mozAvSyncDelay) {
+ statsString += `A/V sync: ${stats.mozAvSyncDelay} ms `;
+ }
+ if (stats.mozJitterBufferDelay) {
+ statsString += `Jitter-buffer delay: ${stats.mozJitterBufferDelay} ms`;
+ }
+
+ return React.DOM.div(null, statsString);'''
+ expected = 'dumpAvStats:function(stats){var statsString="";if(stats.mozAvSyncDelay){statsString+=`A/V sync: ${stats.mozAvSyncDelay} ms `;}\nif(stats.mozJitterBufferDelay){statsString+=`Jitter-buffer delay: ${stats.mozJitterBufferDelay} ms`;}\nreturn React.DOM.div(null,statsString);'
+ self.assertMinified(original, expected, quote_chars="'\"`")
+
+ def testBackticksExpressions(self):
+ original = '`Fifteen is ${a + b} and not ${2 * a + b}.`'
+ self.assertMinified(original, original, quote_chars="'\"`")
+
+ original = '''`Fifteen is ${a +
+b} and not ${2 * a + "b"}.`'''
+ self.assertMinified(original, original, quote_chars="'\"`")
+
+ def testBackticksTagged(self):
+ original = 'tag`Hello ${ a + b } world ${ a * b}`;'
+ self.assertMinified(original, original, quote_chars="'\"`")
+
+ def test_issue_bitbucket_16(self):
+ original = """
+ f = function() {
+ return /DataTree\/(.*)\//.exec(this._url)[1];
+ }
+ """
+ self.assertMinified(
+ original,
+ 'f=function(){return /DataTree\/(.*)\//.exec(this._url)[1];}')
+
+ def test_issue_bitbucket_17(self):
+ original = "// hi\n/^(get|post|head|put)$/i.test('POST')"
+ self.assertMinified(original,
+ "/^(get|post|head|put)$/i.test('POST')")
+
+ def test_issue_6(self):
+ original = '''
+ respond.regex = {
+ comments: /\/\*[^*]*\*+([^/][^*]*\*+)*\//gi,
+ urls: 'whatever'
+ };
+ '''
+ expected = original.replace(' ', '').replace('\n', '')
+ self.assertMinified(original, expected)
+
+ def test_issue_9(self):
+ original = '\n'.join([
+ 'var a = \'hi\' // this is a comment',
+ 'var a = \'hi\' /* this is also a comment */',
+ 'console.log(1) // this is a comment',
+ 'console.log(1) /* this is also a comment */',
+ '1 // this is a comment',
+ '1 /* this is also a comment */',
+ '{} // this is a comment',
+ '{} /* this is also a comment */',
+ '"YOLO" /* this is a comment */',
+ '"YOLO" // this is a comment',
+ '(1 + 2) // comment',
+ '(1 + 2) /* yup still comment */',
+ 'var b'
+ ])
+ expected = '\n'.join([
+ 'var a=\'hi\'',
+ 'var a=\'hi\'',
+ 'console.log(1)',
+ 'console.log(1)',
+ '1',
+ '1',
+ '{}',
+ '{}',
+ '"YOLO"',
+ '"YOLO"',
+ '(1+2)',
+ '(1+2)',
+ 'var b'
+ ])
+ self.assertMinified(expected, expected)
+ self.assertMinified(original, expected)
+
+ def test_newline_between_strings(self):
+ self.assertMinified('"yolo"\n"loyo"', '"yolo"\n"loyo"')
+
+ def test_issue_10_comments_between_tokens(self):
+ self.assertMinified('var/* comment */a', 'var a')
+
+ def test_ends_with_string(self):
+ self.assertMinified('var s = "s"', 'var s="s"')
+
+ def test_short_comment(self):
+ self.assertMinified('a;/**/b', 'a;b')
+
+ def test_shorter_comment(self):
+ self.assertMinified('a;/*/*/b', 'a;b')
+
+ def test_block_comment_with_semicolon(self):
+ self.assertMinified('a;/**/\nb', 'a;b')
+
+ def test_block_comment_With_implicit_semicolon(self):
+ self.assertMinified('a/**/\nvar b', 'a\nvar b')
+
+ def test_issue_9_single_comments(self):
+ original = '''
+ var a = "hello" // this is a comment
+ a += " world"
+ '''
+ self.assertMinified(original, 'var a="hello"\na+=" world"')
+
+ def test_issue_9_multi_comments(self):
+ original = '''
+ var a = "hello" /* this is a comment */
+ a += " world"
+ '''
+ self.assertMinified(original, 'var a="hello"\na+=" world"')
+
+ def test_issue_12_re_nl_if(self):
+ original = '''
+ var re = /\d{4}/
+ if (1) { console.log(2); }'''
+ self.assertMinified(
+ original, 'var re=/\d{4}/\nif(1){console.log(2);}')
+
+ def test_issue_12_re_nl_other(self):
+ original = '''
+ var re = /\d{4}/
+ g = 10'''
+ self.assertMinified(original , 'var re=/\d{4}/\ng=10')
+
+ def test_preserve_copyright(self):
+ original = '''
+ function this() {
+ /*! Copyright year person */
+ console.log('hello!');
+ }
+
+ /*! Copyright blah blah
+ *
+ * Some other text
+ */
+
+ var a;
+ '''
+ expected = """function this(){/*! Copyright year person */
+console.log('hello!');}/*! Copyright blah blah
+ *
+ * Some other text
+ */\n\nvar a;"""
+ self.assertMinified(original, expected)
+
+ def test_issue_14(self):
+ original = 'return x / 1;'
+ self.assertMinified(original, 'return x/1;')
+
+ def test_issue_14_with_char_from_return(self):
+ original = 'return r / 1;'
+ self.assertMinified(original, 'return r/1;')
+
+
+class RegexTests(unittest.TestCase):
+
+ def regex_recognise(self, js):
+ if not jsmin.is_3:
+ if jsmin.cStringIO and not isinstance(js, unicode):
+ # strings can use cStringIO for a 3x performance
+ # improvement, but unicode (in python2) cannot
+ klass = jsmin.cStringIO.StringIO
+ else:
+ klass = jsmin.StringIO.StringIO
+ else:
+ klass = jsmin.io.StringIO
+ ins = klass(js[2:])
+ outs = klass()
+ jsmin.JavascriptMinify(ins, outs).regex_literal(js[0], js[1])
+ return outs.getvalue()
+
+ def assert_regex(self, js_input, expected):
+ assert js_input[0] == '/' # otherwise we should not be testing!
+ recognised = self.regex_recognise(js_input)
+ assert recognised == expected, "\n in: %r\ngot: %r\nexp: %r" % (js_input, recognised, expected)
+
+ def test_simple(self):
+ self.assert_regex('/123/g', '/123/')
+
+ def test_character_class(self):
+ self.assert_regex('/a[0-9]b/g', '/a[0-9]b/')
+
+ def test_character_class_with_slash(self):
+ self.assert_regex('/a[/]b/g', '/a[/]b/')
+
+ def test_escaped_forward_slash(self):
+ self.assert_regex(r'/a\/b/g', r'/a\/b/')
+
+ def test_escaped_back_slash(self):
+ self.assert_regex(r'/a\\/g', r'/a\\/')
+
+ def test_empty_character_class(self):
+ # This one is subtle: an empty character class is not allowed, afaics
+ # from http://regexpal.com/ Chrome Version 44.0.2403.155 (64-bit) Mac
+ # so this char class is interpreted as containing ]/ *not* as char
+ # class [] followed by end-of-regex /.
+ self.assert_regex('/a[]/]b/g', '/a[]/]b/')
+
+ def test_precedence_of_parens(self):
+ # judging from
+ # http://regexpal.com/ Chrome Version 44.0.2403.155 (64-bit) Mac
+ # () have lower precedence than []
+ self.assert_regex('/a([)])b/g', '/a([)])b/')
+ self.assert_regex('/a[(]b/g', '/a[(]b/')
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/third_party/python/jsmin/setup.cfg b/third_party/python/jsmin/setup.cfg
new file mode 100644
index 0000000000..861a9f5542
--- /dev/null
+++ b/third_party/python/jsmin/setup.cfg
@@ -0,0 +1,5 @@
+[egg_info]
+tag_build =
+tag_date = 0
+tag_svn_revision = 0
+
diff --git a/third_party/python/jsmin/setup.py b/third_party/python/jsmin/setup.py
new file mode 100644
index 0000000000..7968aecdd0
--- /dev/null
+++ b/third_party/python/jsmin/setup.py
@@ -0,0 +1,36 @@
+from setuptools import setup
+
+import os, sys, re
+
+os.environ['COPYFILE_DISABLE'] = 'true' # this disables including resource forks in tar files on os x
+
+
+def long_description():
+ return open('README.rst').read() + '\n' + open('CHANGELOG.txt').read()
+
+
+setup(
+ name="jsmin",
+ version=re.search(r'__version__ = ["\']([^"\']+)', open('jsmin/__init__.py').read()).group(1),
+ packages=['jsmin'],
+ description='JavaScript minifier.',
+ long_description=long_description(),
+ author='Dave St.Germain',
+ author_email='dave@st.germa.in',
+ maintainer='Tikitu de Jager',
+ maintainer_email='tikitu+jsmin@logophile.org',
+ test_suite='jsmin.test',
+ license='MIT License',
+ url='https://github.com/tikitu/jsmin/',
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Web Environment',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: MIT License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python :: 3 :: Only',
+ 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
+ 'Topic :: Software Development :: Pre-processors',
+ 'Topic :: Text Processing :: Filters',
+ ]
+)