summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml18
-rw-r--r--AUTHORS1
-rw-r--r--CHANGES211
-rw-r--r--EXAMPLES1
-rw-r--r--MANIFEST.in1
-rw-r--r--Makefile12
-rw-r--r--README.rst6
-rw-r--r--doc/_static/bookcover.pngbin29597 -> 27523 bytes
-rw-r--r--doc/_static/pocoo.pngbin2003 -> 1498 bytes
-rw-r--r--doc/_static/sphinx.pngbin36665 -> 34213 bytes
-rw-r--r--doc/_themes/sphinx13/static/bodybg.pngbin513 -> 429 bytes
-rw-r--r--doc/_themes/sphinx13/static/footerbg.pngbin220 -> 180 bytes
-rw-r--r--doc/_themes/sphinx13/static/headerbg.pngbin230 -> 189 bytes
-rw-r--r--doc/_themes/sphinx13/static/listitem.pngbin207 -> 149 bytes
-rw-r--r--doc/_themes/sphinx13/static/relbg.pngbin223 -> 183 bytes
-rw-r--r--doc/_themes/sphinx13/static/sphinxheader.pngbin12567 -> 11719 bytes
-rw-r--r--doc/conf.py2
-rw-r--r--doc/config.rst84
-rw-r--r--doc/contents.rst2
-rw-r--r--doc/domains.rst26
-rw-r--r--doc/ext/doctest.rst2
-rw-r--r--doc/ext/example_google.py65
-rw-r--r--doc/ext/example_google.rst4
-rw-r--r--doc/ext/example_numpy.py79
-rw-r--r--doc/ext/example_numpy.rst4
-rw-r--r--doc/ext/inheritance.rst2
-rw-r--r--doc/ext/napoleon.rst69
-rw-r--r--doc/ext/todo.rst15
-rw-r--r--doc/ext/viewcode.rst28
-rw-r--r--doc/install.rst2
-rw-r--r--doc/installpython.jpgbin28408 -> 25206 bytes
-rw-r--r--doc/latex.rst151
-rw-r--r--doc/markup/inline.rst6
-rw-r--r--doc/more.pngbin1473 -> 1351 bytes
-rw-r--r--doc/pythonorg.pngbin153185 -> 149780 bytes
-rw-r--r--doc/rest.rst8
-rw-r--r--doc/themes/agogo.pngbin29278 -> 25792 bytes
-rw-r--r--doc/themes/alabaster.pngbin33972 -> 32356 bytes
-rw-r--r--doc/themes/bizstyle.pngbin36234 -> 27139 bytes
-rw-r--r--doc/themes/classic.pngbin43969 -> 39927 bytes
-rw-r--r--doc/themes/fullsize/agogo.pngbin61906 -> 56954 bytes
-rw-r--r--doc/themes/fullsize/alabaster.pngbin55934 -> 40248 bytes
-rw-r--r--doc/themes/fullsize/bizstyle.pngbin103961 -> 75192 bytes
-rw-r--r--doc/themes/fullsize/classic.pngbin78947 -> 72597 bytes
-rw-r--r--doc/themes/fullsize/haiku.pngbin88689 -> 84200 bytes
-rw-r--r--doc/themes/fullsize/nature.pngbin36087 -> 32266 bytes
-rw-r--r--doc/themes/fullsize/pyramid.pngbin107322 -> 102717 bytes
-rw-r--r--doc/themes/fullsize/scrolls.pngbin97121 -> 88111 bytes
-rw-r--r--doc/themes/fullsize/sphinx_rtd_theme.pngbin57187 -> 39411 bytes
-rw-r--r--doc/themes/fullsize/sphinxdoc.pngbin91063 -> 84439 bytes
-rw-r--r--doc/themes/fullsize/traditional.pngbin99337 -> 91744 bytes
-rw-r--r--doc/themes/haiku.pngbin44727 -> 43184 bytes
-rw-r--r--doc/themes/nature.pngbin32041 -> 28536 bytes
-rw-r--r--doc/themes/pyramid.pngbin40085 -> 38805 bytes
-rw-r--r--doc/themes/scrolls.pngbin31717 -> 27800 bytes
-rw-r--r--doc/themes/sphinx_rtd_theme.pngbin31686 -> 29138 bytes
-rw-r--r--doc/themes/sphinxdoc.pngbin33091 -> 30225 bytes
-rw-r--r--doc/themes/traditional.pngbin35367 -> 32258 bytes
-rw-r--r--doc/theming.rst2
-rw-r--r--doc/translation.pngbin14572 -> 13791 bytes
-rw-r--r--doc/tutorial.rst13
-rw-r--r--setup.cfg4
-rw-r--r--setup.py11
-rw-r--r--sphinx/application.py88
-rw-r--r--sphinx/builders/__init__.py26
-rw-r--r--sphinx/builders/applehelp.py95
-rw-r--r--sphinx/builders/changes.py16
-rw-r--r--sphinx/builders/devhelp.py9
-rw-r--r--sphinx/builders/dummy.py4
-rw-r--r--sphinx/builders/epub.py56
-rw-r--r--sphinx/builders/epub3.py15
-rw-r--r--sphinx/builders/gettext.py12
-rw-r--r--sphinx/builders/html.py117
-rw-r--r--sphinx/builders/htmlhelp.py28
-rw-r--r--sphinx/builders/latex.py131
-rw-r--r--sphinx/builders/linkcheck.py17
-rw-r--r--sphinx/builders/manpage.py11
-rw-r--r--sphinx/builders/qthelp.py20
-rw-r--r--sphinx/builders/texinfo.py19
-rw-r--r--sphinx/builders/text.py7
-rw-r--r--sphinx/builders/websupport.py4
-rw-r--r--sphinx/builders/xml.py7
-rw-r--r--sphinx/config.py237
-rw-r--r--sphinx/directives/__init__.py16
-rw-r--r--sphinx/directives/code.py11
-rw-r--r--sphinx/directives/other.py44
-rw-r--r--sphinx/directives/patches.py3
-rw-r--r--sphinx/domains/__init__.py17
-rw-r--r--sphinx/domains/c.py7
-rw-r--r--sphinx/domains/cpp.py262
-rw-r--r--sphinx/domains/javascript.py4
-rw-r--r--sphinx/domains/python.py35
-rw-r--r--sphinx/domains/rst.py4
-rw-r--r--sphinx/domains/std.py196
-rw-r--r--sphinx/environment.py62
-rw-r--r--sphinx/errors.py5
-rw-r--r--sphinx/ext/autodoc.py7
-rw-r--r--sphinx/ext/imgmath.py5
-rw-r--r--sphinx/ext/intersphinx.py20
-rw-r--r--sphinx/ext/jsmath.py6
-rw-r--r--sphinx/ext/mathbase.py2
-rw-r--r--sphinx/ext/mathjax.py5
-rw-r--r--sphinx/ext/napoleon/__init__.py71
-rw-r--r--sphinx/ext/napoleon/docstring.py125
-rw-r--r--sphinx/ext/todo.py7
-rw-r--r--sphinx/ext/viewcode.py9
-rw-r--r--sphinx/io.py11
-rw-r--r--sphinx/make_mode.py19
-rw-r--r--sphinx/quickstart.py1109
-rw-r--r--sphinx/roles.py19
-rw-r--r--sphinx/search/__init__.py38
-rw-r--r--sphinx/search/test (renamed from tests/roots/test-html_extra_path/extra/.htaccess)0
-rw-r--r--sphinx/setup_command.py29
-rw-r--r--sphinx/templates/latex/content.tex_t41
-rw-r--r--sphinx/templates/quickstart/Makefile.new_t21
-rw-r--r--sphinx/templates/quickstart/Makefile_t242
-rw-r--r--sphinx/templates/quickstart/conf.py_t433
-rw-r--r--sphinx/templates/quickstart/make.bat.new_t34
-rw-r--r--sphinx/templates/quickstart/make.bat_t282
-rw-r--r--sphinx/templates/quickstart/master_doc.rst_t22
-rw-r--r--sphinx/texinputs/Makefile_t (renamed from sphinx/texinputs/Makefile)14
-rw-r--r--sphinx/texinputs/needspace.sty35
-rw-r--r--sphinx/texinputs/newfloat.sty737
-rw-r--r--sphinx/texinputs/sphinx.sty691
-rw-r--r--sphinx/texinputs/sphinxhowto.cls21
-rw-r--r--sphinx/texinputs/sphinxmanual.cls66
-rw-r--r--sphinx/texinputs/tabulary.sty4
-rw-r--r--sphinx/themes/agogo/static/bgfooter.pngbin434 -> 276 bytes
-rw-r--r--sphinx/themes/agogo/static/bgtop.pngbin430 -> 266 bytes
-rw-r--r--sphinx/themes/basic/layout.html3
-rw-r--r--sphinx/themes/basic/searchbox.html4
-rw-r--r--sphinx/themes/basic/static/basic.css_t45
-rw-r--r--sphinx/themes/basic/static/comment-bright.pngbin3500 -> 756 bytes
-rw-r--r--sphinx/themes/basic/static/comment-close.pngbin3578 -> 829 bytes
-rw-r--r--sphinx/themes/basic/static/comment.pngbin3445 -> 641 bytes
-rw-r--r--sphinx/themes/basic/static/down-pressed.pngbin347 -> 222 bytes
-rw-r--r--sphinx/themes/basic/static/down.pngbin347 -> 202 bytes
-rw-r--r--sphinx/themes/basic/static/file.pngbin358 -> 286 bytes
-rw-r--r--sphinx/themes/basic/static/jquery-3.1.0.js (renamed from sphinx/themes/basic/static/jquery-1.11.1.js)8518
-rw-r--r--sphinx/themes/basic/static/jquery.js8
-rw-r--r--sphinx/themes/basic/static/minus.pngbin173 -> 90 bytes
-rw-r--r--sphinx/themes/basic/static/plus.pngbin173 -> 90 bytes
-rw-r--r--sphinx/themes/basic/static/searchtools.js_t13
-rw-r--r--sphinx/themes/basic/static/up-pressed.pngbin345 -> 214 bytes
-rw-r--r--sphinx/themes/basic/static/up.pngbin345 -> 203 bytes
-rw-r--r--sphinx/themes/bizstyle/static/background_b01.pngbin87 -> 78 bytes
-rw-r--r--sphinx/themes/epub/layout.html3
-rw-r--r--sphinx/themes/epub/static/epub.css32
-rw-r--r--sphinx/themes/haiku/static/alert_info_32.pngbin1168 -> 1128 bytes
-rw-r--r--sphinx/themes/haiku/static/alert_warning_32.pngbin1060 -> 944 bytes
-rw-r--r--sphinx/themes/haiku/static/bg-page.pngbin147 -> 82 bytes
-rw-r--r--sphinx/themes/haiku/static/bullet_orange.pngbin365 -> 165 bytes
-rw-r--r--sphinx/themes/nonav/layout.html23
-rw-r--r--sphinx/themes/nonav/static/nonav.css568
-rw-r--r--sphinx/themes/nonav/theme.conf8
-rw-r--r--sphinx/themes/pyramid/static/dialog-note.pngbin1461 -> 1394 bytes
-rw-r--r--sphinx/themes/pyramid/static/dialog-seealso.pngbin1473 -> 1351 bytes
-rw-r--r--sphinx/themes/pyramid/static/dialog-todo.pngbin1311 -> 1186 bytes
-rw-r--r--sphinx/themes/pyramid/static/dialog-topic.pngbin1910 -> 1798 bytes
-rw-r--r--sphinx/themes/pyramid/static/dialog-warning.pngbin1365 -> 1280 bytes
-rw-r--r--sphinx/themes/pyramid/static/headerbg.pngbin203 -> 190 bytes
-rw-r--r--sphinx/themes/pyramid/static/middlebg.pngbin2763 -> 101 bytes
-rw-r--r--sphinx/themes/scrolls/static/darkmetal.pngbin25389 -> 25238 bytes
-rw-r--r--sphinx/themes/scrolls/static/headerbg.pngbin298 -> 172 bytes
-rw-r--r--sphinx/themes/scrolls/static/logo.pngbin8654 -> 8305 bytes
-rw-r--r--sphinx/themes/scrolls/static/metal.pngbin7939 -> 7547 bytes
-rw-r--r--sphinx/themes/scrolls/static/navigation.pngbin216 -> 124 bytes
-rw-r--r--sphinx/themes/scrolls/static/watermark.pngbin53916 -> 44483 bytes
-rw-r--r--sphinx/themes/scrolls/static/watermark_blur.pngbin8970 -> 8049 bytes
-rw-r--r--sphinx/themes/sphinxdoc/static/contents.pngbin202 -> 107 bytes
-rw-r--r--sphinx/themes/sphinxdoc/static/navigation.pngbin218 -> 120 bytes
-rw-r--r--sphinx/theming.py5
-rw-r--r--sphinx/transforms.py18
-rw-r--r--sphinx/util/__init__.py47
-rw-r--r--sphinx/util/docfields.py27
-rw-r--r--sphinx/util/fileutil.py80
-rw-r--r--sphinx/util/inspect.py12
-rw-r--r--sphinx/util/jsdump.py2
-rw-r--r--sphinx/util/matching.py21
-rw-r--r--sphinx/util/osutil.py25
-rw-r--r--sphinx/util/pycompat.py2
-rw-r--r--sphinx/util/template.py57
-rw-r--r--sphinx/websupport/search/__init__.py8
-rw-r--r--sphinx/websupport/search/nullsearch.py2
-rw-r--r--sphinx/websupport/search/whooshsearch.py2
-rw-r--r--sphinx/writers/html.py11
-rw-r--r--sphinx/writers/latex.py330
-rw-r--r--test-reqs.txt2
-rwxr-xr-xtests/coverage.py16
-rwxr-xr-xtests/path.py3
-rw-r--r--tests/root/footnote.txt6
-rw-r--r--tests/root/images.txt3
-rw-r--r--tests/root/img.foo.pngbin67765 -> 66247 bytes
-rw-r--r--tests/root/img.pngbin67765 -> 66247 bytes
-rw-r--r--tests/root/includes.txt4
-rw-r--r--tests/root/markup.txt28
-rw-r--r--tests/root/objects.txt2
-rw-r--r--tests/root/rimg.pngbin218 -> 120 bytes
-rw-r--r--tests/root/subdir/img.pngbin67765 -> 66247 bytes
-rw-r--r--tests/root/subdir/simg.pngbin67765 -> 66247 bytes
-rw-r--r--tests/root/testtheme/static/staticimg.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-add_enumerable_node/rimg.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-basic/conf.py7
-rw-r--r--tests/roots/test-basic/index.rst29
-rw-r--r--tests/roots/test-config/conf.py3
-rw-r--r--tests/roots/test-ext-math-simple/conf.py6
-rw-r--r--tests/roots/test-ext-math-simple/index.rst4
-rw-r--r--tests/roots/test-ext-math/math.rst31
-rw-r--r--tests/roots/test-ext-todo/bar.rst4
-rw-r--r--tests/roots/test-ext-todo/conf.py4
-rw-r--r--tests/roots/test-ext-todo/foo.rst4
-rw-r--r--tests/roots/test-ext-todo/index.rst9
-rw-r--r--tests/roots/test-footnotes/rimg.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-html_assets/conf.py (renamed from tests/roots/test-html_extra_path/conf.py)3
-rw-r--r--tests/roots/test-html_assets/extra/.htaccess (renamed from tests/roots/test-html_extra_path/extra/.htpasswd)0
-rw-r--r--tests/roots/test-html_assets/extra/.htpasswd (renamed from tests/roots/test-html_extra_path/extra/API.html_t)0
-rw-r--r--tests/roots/test-html_assets/extra/API.html_t1
-rw-r--r--tests/roots/test-html_assets/extra/css/style.css (renamed from tests/roots/test-html_extra_path/extra/css/style.css)0
-rw-r--r--tests/roots/test-html_assets/extra/rimg.pngbin0 -> 120 bytes
-rw-r--r--tests/roots/test-html_assets/extra/subdir/.htaccess (renamed from tests/roots/test-html_extra_path/subdir/_build/index.html)0
-rw-r--r--tests/roots/test-html_assets/extra/subdir/.htpasswd0
-rw-r--r--tests/roots/test-html_assets/index.rst (renamed from tests/roots/test-html_extra_path/index.rst)0
-rw-r--r--tests/roots/test-html_assets/static/.htaccess0
-rw-r--r--tests/roots/test-html_assets/static/.htpasswd0
-rw-r--r--tests/roots/test-html_assets/static/API.html_t1
-rw-r--r--tests/roots/test-html_assets/static/css/style.css0
-rw-r--r--tests/roots/test-html_assets/static/rimg.pngbin0 -> 120 bytes
-rw-r--r--tests/roots/test-html_assets/static/subdir/.htaccess0
-rw-r--r--tests/roots/test-html_assets/static/subdir/.htpasswd0
-rw-r--r--tests/roots/test-html_assets/subdir/_build/index.html0
-rw-r--r--tests/roots/test-html_assets/subdir/background.pngbin0 -> 120 bytes
-rw-r--r--tests/roots/test-html_extra_path/extra/rimg.pngbin218 -> 0 bytes
-rw-r--r--tests/roots/test-html_extra_path/subdir/background.pngbin218 -> 0 bytes
-rw-r--r--tests/roots/test-image-glob/img.ja.pngbin67765 -> 66247 bytes
-rw-r--r--tests/roots/test-image-glob/img.pngbin67765 -> 66247 bytes
-rw-r--r--tests/roots/test-image-glob/img.zh.pngbin67765 -> 66247 bytes
-rw-r--r--tests/roots/test-image-glob/rimg.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-image-glob/rimg.xx.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-image-glob/subdir/rimg.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-image-glob/subdir/rimg.xx.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-image-glob/testimäge.pngbin67765 -> 66247 bytes
-rw-r--r--tests/roots/test-image-in-section/pic.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-intl/i18n.pngbin67765 -> 66247 bytes
-rw-r--r--tests/roots/test-intl/img.pngbin67765 -> 66247 bytes
-rw-r--r--tests/roots/test-numfig/rimg.pngbin218 -> 120 bytes
-rw-r--r--tests/roots/test-search/index.rst8
-rw-r--r--tests/roots/test-searchadapters/conf.py4
-rw-r--r--tests/roots/test-searchadapters/markup.txt447
-rw-r--r--tests/roots/test-warnings/autodoc_fodder.py7
-rw-r--r--tests/roots/test-warnings/conf.py12
-rw-r--r--tests/roots/test-warnings/index.rst48
-rw-r--r--tests/roots/test-warnings/svgimg.pdfbin0 -> 141783 bytes
-rw-r--r--tests/roots/test-warnings/svgimg.svg158
-rw-r--r--tests/roots/test-warnings/undecodable.rst (renamed from tests/root/undecodable.txt)0
-rw-r--r--tests/roots/test-warnings/wrongenc.inc3
-rwxr-xr-xtests/run.py4
-rw-r--r--tests/test_api_translator.py2
-rw-r--r--tests/test_application.py13
-rw-r--r--tests/test_autodoc.py72
-rw-r--r--tests/test_autodoc_py35.py37
-rw-r--r--tests/test_build.py15
-rw-r--r--tests/test_build_applehelp.py7
-rw-r--r--tests/test_build_gettext.py2
-rw-r--r--tests/test_build_html.py174
-rw-r--r--tests/test_build_latex.py297
-rw-r--r--tests/test_build_texinfo.py31
-rw-r--r--tests/test_catalogs.py1
-rw-r--r--tests/test_config.py38
-rw-r--r--tests/test_correct_year.py12
-rw-r--r--tests/test_directive_code.py37
-rw-r--r--tests/test_domain_cpp.py54
-rw-r--r--tests/test_domain_rst.py2
-rw-r--r--tests/test_environment.py5
-rw-r--r--tests/test_ext_autosummary.py2
-rw-r--r--tests/test_ext_githubpages.py2
-rw-r--r--tests/test_ext_ifconfig.py7
-rw-r--r--tests/test_ext_intersphinx.py3
-rw-r--r--tests/test_ext_math.py25
-rw-r--r--tests/test_ext_napoleon_docstring.py22
-rw-r--r--tests/test_ext_todo.py85
-rw-r--r--tests/test_highlighting.py2
-rw-r--r--tests/test_i18n.py17
-rw-r--r--tests/test_intl.py12
-rw-r--r--tests/test_markup.py25
-rw-r--r--tests/test_search.py17
-rw-r--r--tests/test_searchadapters.py4
-rw-r--r--tests/test_setup_command.py22
-rw-r--r--tests/test_theming.py4
-rw-r--r--tests/test_util_fileutil.py114
-rw-r--r--tests/test_util_i18n.py3
-rw-r--r--tests/test_util_inspect.py70
-rw-r--r--tests/test_util_jsdump.py9
-rw-r--r--tests/test_util_matching.py91
-rw-r--r--tests/test_util_nodes.py3
-rw-r--r--tests/test_writer_latex.py36
-rw-r--r--tests/typing_test_data.py8
-rw-r--r--tests/util.py7
-rw-r--r--tox.ini1
-rwxr-xr-xutils/check_sources.py5
-rwxr-xr-xutils/reindent.py45
-rw-r--r--utils/release-checklist18
301 files changed, 10661 insertions, 8071 deletions
diff --git a/.travis.yml b/.travis.yml
index c468867ae..d07531261 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,16 +13,24 @@ python:
- "pypy"
env:
global:
- - TEST=-v
+ - TEST='-v --with-timer --timer-top-n 25'
matrix:
- DOCUTILS=0.11
- DOCUTILS=0.12
+addons:
+ apt:
+ packages:
+ - graphviz
+ - texlive-latex-recommended
+ - texlive-latex-extra
+ - texlive-fonts-recommended
+ - texlive-fonts-extra
install:
- - pip install -U pip
+ - pip install -U pip setuptools
- pip install docutils==$DOCUTILS
- pip install -r test-reqs.txt
-before_script: flake8
+before_script:
+ - if [[ $TRAVIS_PYTHON_VERSION != '2.6' ]]; then flake8; fi
script:
-
- - if [[ $TRAVIS_PYTHON_VERSION == '3.5' ]]; then make test-async; fi
+ - if [[ $TRAVIS_PYTHON_VERSION == '3.5' ]]; then make style-check test-async; fi
- if [[ $TRAVIS_PYTHON_VERSION != '3.5' ]]; then make test; fi
diff --git a/AUTHORS b/AUTHORS
index dc8e82482..677e814fc 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -41,6 +41,7 @@ Other contributors, listed alphabetically, are:
* Martin Mahner -- nature theme
* Will Maier -- directory HTML builder
* Jacob Mason -- websupport library (GSOC project)
+* Glenn Matthews -- python domain signature improvements
* Roland Meister -- epub builder
* Ezio Melotti -- collapsible sidebar JavaScript
* Daniel Neuhäuser -- JavaScript domain, Python 3 support (GSOC)
diff --git a/CHANGES b/CHANGES
index 87f983bf8..b3eb60219 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,32 +4,230 @@ Release 1.5 (in development)
Incompatible changes
--------------------
-* LaTeX package fancybox is not longer a dependency of sphinx.sty
+* latex, package fancybox is not longer a dependency of sphinx.sty
* Use ``'locales'`` as a default value of `locale_dirs`
+* latex, package ifthen is not any longer a dependency of sphinx.sty
+* latex, style file does not modify fancyvrb's Verbatim (also available as
+ OriginalVerbatim) but uses sphinxVerbatim for name of custom wrapper.
+* latex, package newfloat is no longer a dependency of sphinx.sty (ref #2660;
+ it was shipped with Sphinx since 1.3.4).
+* latex, literal blocks in tables do not use OriginalVerbatim but
+ sphinxVerbatimintable which handles captions and wraps lines(ref #2704).
+* latex, replace ``pt`` by TeX equivalent ``bp`` if found in ``width`` or
+ ``height`` attribute of an image.
+* latex, if ``width`` or ``height`` attribute of an image is given with no unit,
+ use ``px`` rather than ignore it.
+* latex: Separate stylesheets of pygments to independent .sty file
+* #2454: The filename of sourcelink is now changed. The value of
+ `html_sourcelink_suffix` will be appended to the original filename (like
+ ``index.rst.txt``).
+* ``sphinx.util.copy_static_entry()`` is now deprecated.
+ Use ``sphinx.util.fileutil.copy_asset()`` instead.
+* ``sphinx.util.osutil.filecopy()`` skips copying if the file has not been changed
+ (ref: #2510, #2753)
+* Internet Explorer 6-8, Opera 12.1x or Safari 5.1+ support is dropped
+ because jQuery version is updated from 1.11.0 to 3.1.0 (ref: #2634, #2773)
+* QtHelpBuilder doens't generate search page (ref: #2352)
+* QtHelpBuilder uses ``nonav`` theme instead of default one
+ to improve readability.
+* latex: To provide good default settings to Japanese docs, Sphinx uses ``jsbooks``
+ as a docclass by default if the ``language`` is ``ja``.
+* latex: To provide good default settings to Japanese docs, Sphinx uses
+ ``jreport`` and ``jsbooks`` as a docclass by default if the ``language`` is
+ ``ja``.
+* ``sphinx-quickstart`` now allows a project version is empty
+* Fix :download: role on epub/qthelp builder. They ignore the role because they don't support it.
+* ``sphinx.ext.viewcode`` doesn't work on epub building by default. ``viewcode_enable_epub`` option
+* ``sphinx.ext.viewcode`` disabled on singlehtml builder.
Features added
--------------
* Add ``:caption:`` option for sphinx.ext.inheritance_diagram.
-* #894: Add ``lualatexpdf`` and ``xelatexpdf`` as a make target to build PDF using lualatex or xelatex
* #2471: Add config variable for default doctest flags.
* Convert linkcheck builder to requests for better encoding handling
* #2463, #2516: Add keywords of "meta" directive to search index
* ``:maxdepth:`` option of toctree affects ``secnumdepth`` (ref: #2547)
* #2575: Now ``sphinx.ext.graphviz`` allows ``:align:`` option
+* Show warnings if unknown key is specified to `latex_elements`
+* Show warnings if no domains match with `primary_domain` (ref: #2001)
+* C++, show warnings when the kind of role is misleading for the kind
+ of target it refers to (e.g., using the `class` role for a function).
+* latex, writer abstracts more of text styling into customizable macros, e.g.
+ the ``visit_emphasis`` will output ``\sphinxstyleemphasis`` rather than
+ ``\emph`` (which may be in use elsewhere or in an added LaTeX package). See
+ list at end of ``sphinx.sty`` (ref: #2686)
+* latex, public names for environments and parameters used by note, warning,
+ and other admonition types, allowing full customizability from the
+ ``'preamble'`` key or an input file (ref: feature request #2674, #2685)
+* latex, better computes column widths of some tables (as a result, there will
+ be slight changes as tables now correctly fill the line width; ref: #2708)
+* latex, sphinxVerbatim environment is more easily customizable (ref: #2704).
+ In addition to already existing VerbatimColor and VerbatimBorderColor:
+
+ - two lengths ``\sphinxverbatimsep`` and ``\sphinxverbatimborder``,
+ - booleans ``\ifsphinxverbatimwithframe`` and ``\ifsphinxverbatimwrapslines``.
+
+* latex, captions for literal blocks inside tables are handled, and long code
+ lines wrapped to fit table cell (ref: #2704)
+* #2597: Show warning messages as darkred
+* latex, allow image dimensions using px unit (default is 96px=1in)
+* Show warnings if invalid dimension units found
+* #2650: Add ``--pdb`` option to setup.py command
+* latex, make the use of ``\small`` for code listings customizable (ref #2721)
+* #2663: Add ``--warning-is-error`` option to setup.py command
+* Show warnings if deprecated latex options are used
+* Add sphinx.config.ENUM to check the config values is in candidates
+* math: Add hyperlink marker to each equations in HTML output
+* Add new theme ``nonav`` that doesn't include any navigation links.
+ This is for any help generator like qthelp.
+* #2680: `sphinx.ext.todo` now emits warnings if `todo_emit_warnings` enabled.
+ Also, it emits an additional event named `todo-defined` to handle the TODO
+ entries in 3rd party extensions.
+* Python domain signature parser now uses the xref mixin for 'exceptions',
+ allowing exception classes to be autolinked.
+* #2513: Add `latex_engine` to switch the LaTeX engine by conf.py
+* #2682: C++, basic support for attributes (C++11 style and GNU style).
+ The new configuration variables 'cpp_id_attributes' and 'cpp_paren_attributes'
+ can be used to introduce custom attributes.
+* #1958: C++, add configuration variable 'cpp_index_common_prefix' for removing
+ prefixes from the index text of C++ objects.
* C++, added concept directive. Thanks to mickk-on-cpp.
* C++, added support for template introduction syntax. Thanks to mickk-on-cpp.
Bugs fixed
----------
+* #2707: (latex) the column width is badly computed for tabular
+* #2799: Sphinx installs roles and directives automatically on importing sphinx
+ module. Now Sphinx installs them on running application.
+
Documentation
-------------
-Release 1.4.2 (in development)
+Release 1.4.6 (in development)
==============================
+Bugs fixed
+----------
+
+* applehelp: Sphinx crashes if ``hiutil`` or ``codesign`` commands not found
+* Fix ``make clean`` abort issue when build dir contains regular files like ``DS_Store``.
+* Reduce epubcheck warnings/errors:
+
+ * Fix DOCTYPE to html5
+ * Change extension from .html to .xhtml.
+ * Disable search page on epub results
+
+* #2778: Fix autodoc crashes if obj.__dict__ is a property method and raises exception
+* Fix duplicated toc in epub3 output.
+* #2775: Fix failing linkcheck with servers not supporting identidy encoding
+* #2833: Fix formatting instance annotations in ext.autodoc.
+* #1911: ``-D`` option of `sphinx-build` does not override the ``extensions`` variable
+
+Release 1.4.5 (released Jul 13, 2016)
+=====================================
+
+Incompatible changes
+--------------------
+
+* latex, inclusion of non-inline images from image directive resulted in
+ non-coherent whitespaces depending on original image width; new behaviour
+ by necessity differs from earlier one in some cases. (ref: #2672)
+* latex, use of ``\includegraphics`` to refer to Sphinx custom variant is
+ deprecated; in future it will revert to original LaTeX macro, custom one
+ already has alternative name ``\sphinxincludegraphics``.
+
+Features added
+--------------
+
+* new config option ``latex_keep_old_macro_names``, defaults to True. If False,
+ lets macros (for text styling) be defined only with ``\sphinx``-prefixed names.
+* latex writer allows user customization of "shadowed" boxes (topics), via
+ three length variables.
+* woff-format web font files now supported by the epub builder.
+
+Bugs fixed
+----------
+
+* jsdump fix for python 3: fixes the HTML search on python > 3
+* #2676: (latex) Error with verbatim text in captions since Sphinx 1.4.4
+* #2629: memoir class crashes LaTeX. Fixed ``by latex_keep_old_macro_names=False`` (ref 2675)
+* #2684: `sphinx.ext.intersphinx` crashes with six-1.4.1
+* #2679: ``float`` package needed for ``'figure_align': 'H'`` latex option
+* #2671: image directive may lead to inconsistent spacing in pdf
+* #2705: ``toctree`` generates empty bullet_list if ``:titlesonly:`` specified
+* #2479: `sphinx.ext.viewcode` uses python2 highlighter by default
+* #2700: HtmlHelp builder has hard coded index.html
+* latex, since 1.4.4 inline literal text is followed by spurious space
+* #2722: C++, fix id generation for var/member declarations to include namespaces.
+* latex, images (from image directive) in lists or quoted blocks did not obey
+ indentation (fixed together with #2671)
+* #2733: since Sphinx-1.4.4 ``make latexpdf`` generates lots of hyperref warnings
+* #2731: `sphinx.ext.autodoc` does not access propertymethods which raises any
+ exceptions
+* #2666: C++, properly look up nested names involving constructors.
+* #2579: Could not refer a label including both spaces and colons via
+ `sphinx.ext.intersphinx`
+* #2718: Sphinx crashes if the document file is not readable
+* #2699: hyperlinks in help HTMLs are broken if `html_file_suffix` is set
+* #2723: extra spaces in latex pdf output from multirow cell
+* #2735: latexpdf ``Underfull \hbox (badness 10000)`` warnings from title page
+* #2667: latex crashes if resized images appeared in section title
+* #2763: (html) Provide default value for required ``alt`` attribute for image
+ tags of SVG source, required to validate and now consistent w/ other formats.
+
+
+Release 1.4.4 (released Jun 12, 2016)
+=====================================
+
+Bugs fixed
+----------
+
+* #2630: Latex sphinx.sty Notice Enviroment formatting problem
+* #2632: Warning directives fail in quote environment latex build
+* #2633: Sphinx crashes with old styled indices
+* Fix a ``\begin{\minipage}`` typo in sphinx.sty from 1.4.2 (ref: 68becb1)
+* #2622: Latex produces empty pages after title and table of contents
+* #2640: 1.4.2 LaTeX crashes if code-block inside warning directive
+* Let LaTeX use straight quotes also in inline code (ref #2627)
+* #2351: latex crashes if enumerated lists are placed on footnotes
+* #2646: latex crashes if math contains twice empty lines
+* #2480: `sphinx.ext.autodoc`: memory addresses were shown
+* latex: allow code-blocks appearing inside lists and quotes at maximal nesting
+ depth (ref #777, #2624, #2651)
+* #2635: Latex code directives produce inconsistent frames based on viewing
+ resolution
+* #2639: Sphinx now bundles iftex.sty
+* Failed to build PDF with framed.sty 0.95
+* Sphinx now bundles needspace.sty
+
+
+Release 1.4.3 (released Jun 5, 2016)
+====================================
+
+Bugs fixed
+----------
+
+* #2530: got "Counter too large" error on building PDF if large numbered
+ footnotes existed in admonitions
+* ``width`` option of figure directive does not work if ``align`` option specified at same time (ref: #2595)
+* #2590: The ``inputenc`` package breaks compiling under lualatex and xelatex
+* #2540: date on latex front page use different font
+* Suppress "document isn't included in any toctree" warning if the document is included (ref: #2603)
+* #2614: Some tables in PDF output will end up shifted if user sets non zero
+ \parindent in preamble
+* #2602: URL redirection breaks the hyperlinks generated by `sphinx.ext.intersphinx`
+* #2613: Show warnings if merged extensions are loaded
+* #2619: make sure amstext LaTeX package always loaded (ref: d657225, 488ee52,
+ 9d82cad and #2615)
+* #2593: latex crashes if any figures in the table
+
+
+Release 1.4.2 (released May 29, 2016)
+=====================================
+
Features added
--------------
@@ -64,7 +262,8 @@ Bugs fixed
* #2397: Setup shorthandoff for turkish documents
* #2447: VerbatimBorderColor wrongly used also for captions of PDF
* #2456: C++, fix crash related to document merging (e.g., singlehtml and Latex builders).
-* #2446: latex(pdf) sets local tables of contents (or more generally topic nodes) in unbreakable boxes, causes overflow at bottom
+* #2446: latex(pdf) sets local tables of contents (or more generally topic
+ nodes) in unbreakable boxes, causes overflow at bottom
* #2476: Omit MathJax markers if :nowrap: is given
* #2465: latex builder fails in case no caption option is provided to toctree directive
* Sphinx crashes if self referenced toctree found
@@ -100,6 +299,7 @@ Bugs fixed
* #2581: The search doesn't work if language="es" (spanish)
* #2382: Adjust spacing after abbreviations on figure numbers in LaTeX writer
* #2383: The generated footnote by `latex_show_urls` overflows lines
+* #2497, #2552: The label of search button does not fit for the button itself
Release 1.4.1 (released Apr 12, 2016)
@@ -272,7 +472,8 @@ Bugs fixed
is highlighted as Python 3 (which is mostly a superset of Python 2) if possible.
To get the old behavior back, add ``highlight_language = "python"`` to conf.py.
* #2329: Refresh environment forcely if source directory has changed.
-* #2331: Fix code-blocks are filled by block in dvi; remove ``xcdraw`` option from xcolor package
+* #2331: Fix code-blocks are filled by block in dvi; remove ``xcdraw`` option from
+ xcolor package
* Fix the confval type checker emits warnings if unicode is given to confvals which expects string value
* #2360: Fix numref in LaTeX output is broken
* #2361: Fix additional paragraphs inside the "compound" directive are indented
diff --git a/EXAMPLES b/EXAMPLES
index e6d7cedbd..e5d27f747 100644
--- a/EXAMPLES
+++ b/EXAMPLES
@@ -61,6 +61,7 @@ Documentation using the classic theme
* Quex: http://quex.sourceforge.net/doc/html/main.html
* Ring programming language: http://ring-lang.sourceforge.net/doc/index.html
* Scapy: http://www.secdev.org/projects/scapy/doc/
+* Seaborn: https://stanford.edu/~mwaskom/software/seaborn/
* Segway: http://noble.gs.washington.edu/proj/segway/doc/1.1.0/segway.html
* SimPy: http://simpy.readthedocs.org/en/latest/
* SymPy: http://docs.sympy.org/
diff --git a/MANIFEST.in b/MANIFEST.in
index bb0be4958..5e95299de 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -13,6 +13,7 @@ include sphinx-build.py
include sphinx-quickstart.py
include sphinx-apidoc.py
+recursive-include sphinx/templates *
recursive-include sphinx/texinputs *
recursive-include sphinx/themes *
recursive-include sphinx/locale *
diff --git a/Makefile b/Makefile
index 02854840e..2828f1a25 100644
--- a/Makefile
+++ b/Makefile
@@ -6,10 +6,11 @@ PYTHON ?= python
DONT_CHECK = -i build -i dist -i sphinx/style/jquery.js \
-i sphinx/pycode/pgen2 -i sphinx/util/smartypants.py \
-i .ropeproject -i doc/_build -i tests/path.py \
- -i tests/coverage.py -i env -i utils/convert.py \
+ -i tests/coverage.py -i utils/convert.py \
-i tests/typing_test_data.py \
-i tests/test_autodoc_py35.py \
-i tests/build \
+ -i tests/roots/test-warnings/undecodable.rst \
-i sphinx/search/da.py \
-i sphinx/search/de.py \
-i sphinx/search/en.py \
@@ -33,12 +34,15 @@ all: clean-pyc clean-backupfiles style-check test
style-check:
@$(PYTHON) utils/check_sources.py $(DONT_CHECK) .
-clean: clean-pyc clean-patchfiles clean-backupfiles clean-generated
+clean: clean-pyc clean-pycache clean-patchfiles clean-backupfiles clean-generated clean-testfiles
clean-pyc:
find . -name '*.pyc' -exec rm -f {} +
find . -name '*.pyo' -exec rm -f {} +
+clean-pycache:
+ find . -name __pycache__ -exec rm -rf {} +
+
clean-patchfiles:
find . -name '*.orig' -exec rm -f {} +
find . -name '*.rej' -exec rm -f {} +
@@ -50,6 +54,10 @@ clean-backupfiles:
clean-generated:
rm -f utils/*3.py*
+clean-testfiles:
+ rm -rf tests/build
+ rm -rf .tox/
+
pylint:
@pylint --rcfile utils/pylintrc sphinx
diff --git a/README.rst b/README.rst
index 391d0bd1a..384e2cc6a 100644
--- a/README.rst
+++ b/README.rst
@@ -33,6 +33,12 @@ Install from cloned source as editable::
pip install -e .
+Release signatures
+==================
+
+Releases are signed with `498D6B9E <https://pgp.mit.edu/pks/lookup?op=vindex&search=0x102C2C17498D6B9E>`_
+
+
Reading the docs
================
diff --git a/doc/_static/bookcover.png b/doc/_static/bookcover.png
index 5b521b67b..0a8167fcc 100644
--- a/doc/_static/bookcover.png
+++ b/doc/_static/bookcover.png
Binary files differ
diff --git a/doc/_static/pocoo.png b/doc/_static/pocoo.png
index 67663b976..1648bb8d7 100644
--- a/doc/_static/pocoo.png
+++ b/doc/_static/pocoo.png
Binary files differ
diff --git a/doc/_static/sphinx.png b/doc/_static/sphinx.png
index 4bd9c7536..0a103cd3e 100644
--- a/doc/_static/sphinx.png
+++ b/doc/_static/sphinx.png
Binary files differ
diff --git a/doc/_themes/sphinx13/static/bodybg.png b/doc/_themes/sphinx13/static/bodybg.png
index ebe92f669..6f667b99e 100644
--- a/doc/_themes/sphinx13/static/bodybg.png
+++ b/doc/_themes/sphinx13/static/bodybg.png
Binary files differ
diff --git a/doc/_themes/sphinx13/static/footerbg.png b/doc/_themes/sphinx13/static/footerbg.png
index df783e2c7..d1bcb009b 100644
--- a/doc/_themes/sphinx13/static/footerbg.png
+++ b/doc/_themes/sphinx13/static/footerbg.png
Binary files differ
diff --git a/doc/_themes/sphinx13/static/headerbg.png b/doc/_themes/sphinx13/static/headerbg.png
index 22830f99e..522504964 100644
--- a/doc/_themes/sphinx13/static/headerbg.png
+++ b/doc/_themes/sphinx13/static/headerbg.png
Binary files differ
diff --git a/doc/_themes/sphinx13/static/listitem.png b/doc/_themes/sphinx13/static/listitem.png
index e45715f91..f7f814d00 100644
--- a/doc/_themes/sphinx13/static/listitem.png
+++ b/doc/_themes/sphinx13/static/listitem.png
Binary files differ
diff --git a/doc/_themes/sphinx13/static/relbg.png b/doc/_themes/sphinx13/static/relbg.png
index 2006af7d2..68a9b77eb 100644
--- a/doc/_themes/sphinx13/static/relbg.png
+++ b/doc/_themes/sphinx13/static/relbg.png
Binary files differ
diff --git a/doc/_themes/sphinx13/static/sphinxheader.png b/doc/_themes/sphinx13/static/sphinxheader.png
index 12988c3d1..845da4ab9 100644
--- a/doc/_themes/sphinx13/static/sphinxheader.png
+++ b/doc/_themes/sphinx13/static/sphinxheader.png
Binary files differ
diff --git a/doc/conf.py b/doc/conf.py
index 753ffab4c..f3bf569f8 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -47,7 +47,7 @@ epub_fix_images = False
epub_max_image_width = 0
epub_show_urls = 'inline'
epub_use_index = False
-epub_guide = (('toc', 'contents.html', u'Table of Contents'),)
+epub_guide = (('toc', 'contents.xhtml', u'Table of Contents'),)
latex_documents = [('contents', 'sphinx.tex', 'Sphinx Documentation',
'Georg Brandl', 'manual', 1)]
diff --git a/doc/config.rst b/doc/config.rst
index f0a290a23..66d4b9da6 100644
--- a/doc/config.rst
+++ b/doc/config.rst
@@ -56,7 +56,7 @@ General configuration
.. confval:: extensions
- A list of strings that are module names of Sphinx extensions. These can be
+ A list of strings that are module names of :ref:`extensions`. These can be
extensions coming with Sphinx (named ``sphinx.ext.*``) or custom ones.
Note that you can extend :data:`sys.path` within the conf file if your
@@ -870,6 +870,13 @@ that use Sphinx's HTMLWriter class.
.. versionadded:: 0.6
+.. confval:: html_sourcelink_suffix
+
+ Suffix to be appended to source links (see :confval:`html_show_sourcelink`),
+ unless they have this suffix already. Default is ``'.txt'``.
+
+ .. versionadded:: 1.5
+
.. confval:: html_use_opensearch
If nonempty, an `OpenSearch <http://www.opensearch.org/Home>`_ description file will be
@@ -1460,7 +1467,17 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
Options for LaTeX output
------------------------
-These options influence LaTeX output.
+These options influence LaTeX output. See further :doc:`latex`.
+
+.. confval:: latex_engine
+
+ The LaTeX engine to build the docs. The setting can have the following
+ values:
+
+ * pdflatex -- PDFLaTeX (default)
+ * xelatex -- XeLaTeX
+ * lualatex -- LuaLaTeX
+ * platex -- pLaTeX (default if `language` is 'ja')
.. confval:: latex_documents
@@ -1568,6 +1585,21 @@ These options influence LaTeX output.
value selected the ``'inline'`` display. For backwards compatibility,
``True`` is still accepted.
+.. confval:: latex_keep_old_macro_names
+
+ If ``True`` (default) the ``\strong``, ``\code``, ``\bfcode``, ``\email``,
+ ``\tablecontinued``, ``\titleref``, ``\menuselection``, ``\accelerator``,
+ ``\crossref``, ``\termref``, and ``\optional`` text styling macros are
+ pre-defined by Sphinx and may be user-customized by some
+ ``\renewcommand``'s inserted either via ``'preamble'`` key or :dudir:`raw
+ <raw-data-pass-through>` directive. If ``False``, only ``\sphinxstrong``,
+ etc... macros are defined (and may be redefined by user). Setting to
+ ``False`` may help solve macro name conflicts caused by user-added latex
+ packages.
+
+ .. versionadded:: 1.4.5
+
+
.. confval:: latex_elements
.. versionadded:: 0.5
@@ -1586,6 +1618,15 @@ These options influence LaTeX output.
``'pointsize'``
Point size option of the document class (``'10pt'``, ``'11pt'`` or
``'12pt'``), default ``'10pt'``.
+ ``'pxunit'``
+ the value of the ``px`` when used in image attributes ``width`` and
+ ``height``. The default value is ``'49336sp'`` which achieves
+ ``96px=1in`` (``1in = 72.27*65536 = 4736286.72sp``, and all dimensions
+ in TeX are internally integer multiples of ``sp``). To obtain for
+ example ``100px=1in``, one can use ``'0.01in'`` but it is more precise
+ to use ``'47363sp'``. To obtain ``72px=1in``, use ``'1bp'``.
+
+ .. versionadded:: 1.5
``'babel'``
"babel" package inclusion, default ``'\\usepackage{babel}'``.
``'fontpkg'``
@@ -1608,7 +1649,7 @@ These options influence LaTeX output.
.. versionadded:: 1.4
``'preamble'``
- Additional preamble content, default empty.
+ Additional preamble content, default empty. See :doc:`latex`.
``'figure_align'``
Latex figure float alignment, default 'htbp' (here, top, bottom, page).
Whenever an image doesn't fit into the current page, it will be
@@ -1627,7 +1668,7 @@ These options influence LaTeX output.
``'\\usepackage[utf8]{inputenc}'`` when using pdflatex.
Otherwise unset.
- .. versionchanged:: 1.5
+ .. versionchanged:: 1.4.3
Previously ``'\\usepackage[utf8]{inputenc}'`` was used for all
compilers.
``'cmappkg'``
@@ -1678,6 +1719,11 @@ These options influence LaTeX output.
.. versionadded:: 1.0
+ .. versionchanged:: 1.5
+
+ In Japanese docs(`language` is ``ja``), ``'jreport'`` is used for
+ ``'howto'`` and ``'jsbooks'`` is used for ``'manual'`` by default.
+
.. confval:: latex_additional_files
A list of file names, relative to the configuration directory, to copy to the
@@ -1953,3 +1999,33 @@ Options for the XML builder
constructs ``*``, ``?``, ``[...]`` and ``[!...]`` with the feature that
these all don't match slashes. A double star ``**`` can be used to match
any sequence of characters *including* slashes.
+
+
+.. _cpp-config:
+
+Options for the C++ domain
+--------------------------
+
+.. confval:: cpp_index_common_prefix
+
+ A list of prefixes that will be ignored when sorting C++ objects in the global index.
+ For example ``['awesome_lib::']``.
+
+ .. versionadded:: 1.5
+
+.. confval:: cpp_id_attributes
+
+ A list of strings that the parser additionally should accept as attributes.
+ This can for example be used when attributes have been ``#define`` d for portability.
+
+ .. versionadded:: 1.5
+
+.. confval:: cpp_paren_attributes
+
+ A list of strings that the parser additionally should accept as attributes with one argument.
+ That is, if ``my_align_as`` is in the list, then ``my_align_as(X)`` is parsed as an attribute
+ for all strings ``X`` that have balanced brances (``()``, ``[]``, and ``{}``).
+ This can for example be used when attributes have been ``#define`` d for portability.
+
+ .. versionadded:: 1.5
+
diff --git a/doc/contents.rst b/doc/contents.rst
index a51910b81..79a10493d 100644
--- a/doc/contents.rst
+++ b/doc/contents.rst
@@ -1,3 +1,4 @@
+
.. _contents:
Sphinx documentation contents
@@ -17,6 +18,7 @@ Sphinx documentation contents
intl
theming
templating
+ latex
extensions
extdev/index
websupport
diff --git a/doc/domains.rst b/doc/domains.rst
index 7128067d3..7c23056d8 100644
--- a/doc/domains.rst
+++ b/doc/domains.rst
@@ -359,6 +359,18 @@ single word, like this::
:param int priority: The priority of the message, can be a number 1-5
+.. versionadded:: 1.5
+
+Container types such as lists and dictionaries can be linked automatically
+using the following syntax::
+
+ :type priorities: list(int)
+ :type priorities: list[int]
+ :type mapping: dict(str, int)
+ :type mapping: dict[str, int]
+ :type point: tuple(float, float)
+ :type point: tuple[float, float]
+
.. _python-roles:
Cross-referencing Python objects
@@ -545,10 +557,10 @@ a visibility statement (``public``, ``private`` or ``protected``).
Full and partial template specialisations can be declared::
- .. cpp::class:: template<> \
+ .. cpp:class:: template<> \
std::array<bool, 256>
- .. cpp::class:: template<typename T> \
+ .. cpp:class:: template<typename T> \
std::array<T, 42>
@@ -680,9 +692,9 @@ a visibility statement (``public``, ``private`` or ``protected``).
Describe an enumerator, optionally with its value defined, e.g.,::
- .. cpp::enumerator:: MyEnum::myEnumerator
+ .. cpp:enumerator:: MyEnum::myEnumerator
- .. cpp::enumerator:: MyEnum::myOtherEnumerator = 42
+ .. cpp:enumerator:: MyEnum::myOtherEnumerator = 42
.. rst:directive:: .. cpp:concept:: template-parameter-list name
@@ -972,6 +984,12 @@ References to partial specialisations must always include the template parameter
Currently the lookup only succeed if the template parameter identifiers are equal strings.
+Configuration Variables
+~~~~~~~~~~~~~~~~~~~~~~~
+
+See :ref:`cpp-config`.
+
+
The Standard Domain
-------------------
diff --git a/doc/ext/doctest.rst b/doc/ext/doctest.rst
index 3d4f66a9a..818b86007 100644
--- a/doc/ext/doctest.rst
+++ b/doc/ext/doctest.rst
@@ -182,7 +182,7 @@ The doctest extension uses the following configuration values:
.. confval:: doctest_default_flags
By default, these options are enabled:
-
+
- ``ELLIPSIS``, allowing you to put ellipses in the expected output that
match anything in the actual output;
- ``IGNORE_EXCEPTION_DETAIL``, causing everything following the leftmost
diff --git a/doc/ext/example_google.py b/doc/ext/example_google.py
index 81a312cfd..34a720e36 100644
--- a/doc/ext/example_google.py
+++ b/doc/ext/example_google.py
@@ -43,6 +43,39 @@ on the first line, separated by a colon.
"""
+def function_with_types_in_docstring(param1, param2):
+ """Example function with types documented in the docstring.
+
+ `PEP 484`_ type annotations are supported. If attribute, parameter, and
+ return types are annotated according to `PEP 484`_, they do not need to be
+ included in the docstring:
+
+ Args:
+ param1 (int): The first parameter.
+ param2 (str): The second parameter.
+
+ Returns:
+ bool: The return value. True for success, False otherwise.
+
+ .. _PEP 484:
+ https://www.python.org/dev/peps/pep-0484/
+
+ """
+
+
+def function_with_pep484_type_annotations(param1: int, param2: str) -> bool:
+ """Example function with PEP 484 type annotations.
+
+ Args:
+ param1: The first parameter.
+ param2: The second parameter.
+
+ Returns:
+ The return value. True for success, False otherwise.
+
+ """
+
+
def module_level_function(param1, param2=None, *args, **kwargs):
"""This is an example of a module level function.
@@ -50,9 +83,6 @@ def module_level_function(param1, param2=None, *args, **kwargs):
of each parameter is required. The type and description of each parameter
is optional, but should be included if not obvious.
- Parameter types -- if given -- should be specified according to
- `PEP 484`_, though `PEP 484`_ conformance isn't required or enforced.
-
If \*args or \*\*kwargs are accepted,
they should be listed as ``*args`` and ``**kwargs``.
@@ -67,7 +97,7 @@ def module_level_function(param1, param2=None, *args, **kwargs):
Args:
param1 (int): The first parameter.
- param2 (Optional[str]): The second parameter. Defaults to None.
+ param2 (:obj:`str`, optional): The second parameter. Defaults to None.
Second line of description should be indented.
*args: Variable length argument list.
**kwargs: Arbitrary keyword arguments.
@@ -94,10 +124,6 @@ def module_level_function(param1, param2=None, *args, **kwargs):
that are relevant to the interface.
ValueError: If `param2` is equal to `param1`.
-
- .. _PEP 484:
- https://www.python.org/dev/peps/pep-0484/
-
"""
if param1 == param2:
raise ValueError('param1 may not be equal to param2')
@@ -139,7 +165,7 @@ class ExampleError(Exception):
Args:
msg (str): Human readable string describing the exception.
- code (Optional[int]): Error code.
+ code (:obj:`int`, optional): Error code.
Attributes:
msg (str): Human readable string describing the exception.
@@ -163,16 +189,9 @@ class ExampleClass(object):
Properties created with the ``@property`` decorator should be documented
in the property's getter method.
- Attribute and property types -- if given -- should be specified according
- to `PEP 484`_, though `PEP 484`_ conformance isn't required or enforced.
-
Attributes:
attr1 (str): Description of `attr1`.
- attr2 (Optional[int]): Description of `attr2`.
-
-
- .. _PEP 484:
- https://www.python.org/dev/peps/pep-0484/
+ attr2 (:obj:`int`, optional): Description of `attr2`.
"""
@@ -190,20 +209,20 @@ class ExampleClass(object):
Args:
param1 (str): Description of `param1`.
- param2 (Optional[int]): Description of `param2`. Multiple
+ param2 (:obj:`int`, optional): Description of `param2`. Multiple
lines are supported.
- param3 (List[str]): Description of `param3`.
+ param3 (list(str)): Description of `param3`.
"""
self.attr1 = param1
self.attr2 = param2
self.attr3 = param3 #: Doc comment *inline* with attribute
- #: List[str]: Doc comment *before* attribute, with type specified
+ #: list(str): Doc comment *before* attribute, with type specified
self.attr4 = ['attr4']
self.attr5 = None
- """Optional[str]: Docstring *after* attribute, with type specified."""
+ """str: Docstring *after* attribute, with type specified."""
@property
def readonly_property(self):
@@ -212,8 +231,8 @@ class ExampleClass(object):
@property
def readwrite_property(self):
- """List[str]: Properties with both a getter and setter should only
- be documented in their getter method.
+ """list(str): Properties with both a getter and setter
+ should only be documented in their getter method.
If the setter method contains notable behavior, it should be
mentioned here.
diff --git a/doc/ext/example_google.rst b/doc/ext/example_google.rst
index 06508082c..a06f161b9 100644
--- a/doc/ext/example_google.rst
+++ b/doc/ext/example_google.rst
@@ -9,7 +9,9 @@ Example Google Style Python Docstrings
:ref:`example_numpy`
-Download: :download:`example_google.py <example_google.py>`
+.. only:: builder_html
+
+ Download: :download:`example_google.py <example_google.py>`
.. literalinclude:: example_google.py
:language: python
diff --git a/doc/ext/example_numpy.py b/doc/ext/example_numpy.py
index bb91cac82..7a2db94cc 100644
--- a/doc/ext/example_numpy.py
+++ b/doc/ext/example_numpy.py
@@ -37,6 +37,7 @@ module_level_variable1 : int
one convention to document module level variables and be consistent
with it.
+
.. _NumPy Documentation HOWTO:
https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
@@ -52,6 +53,52 @@ on the first line, separated by a colon.
"""
+def function_with_types_in_docstring(param1, param2):
+ """Example function with types documented in the docstring.
+
+ `PEP 484`_ type annotations are supported. If attribute, parameter, and
+ return types are annotated according to `PEP 484`_, they do not need to be
+ included in the docstring:
+
+ Parameters
+ ----------
+ param1 : int
+ The first parameter.
+ param2 : str
+ The second parameter.
+
+ Returns
+ -------
+ bool
+ True if successful, False otherwise.
+
+ .. _PEP 484:
+ https://www.python.org/dev/peps/pep-0484/
+
+ """
+
+
+def function_with_pep484_type_annotations(param1: int, param2: str) -> bool:
+ """Example function with PEP 484 type annotations.
+
+ The return type must be duplicated in the docstring to comply
+ with the NumPy docstring style.
+
+ Parameters
+ ----------
+ param1
+ The first parameter.
+ param2
+ The second parameter.
+
+ Returns
+ -------
+ bool
+ True if successful, False otherwise.
+
+ """
+
+
def module_level_function(param1, param2=None, *args, **kwargs):
"""This is an example of a module level function.
@@ -59,9 +106,6 @@ def module_level_function(param1, param2=None, *args, **kwargs):
The name of each parameter is required. The type and description of each
parameter is optional, but should be included if not obvious.
- Parameter types -- if given -- should be specified according to
- `PEP 484`_, though `PEP 484`_ conformance isn't required or enforced.
-
If \*args or \*\*kwargs are accepted,
they should be listed as ``*args`` and ``**kwargs``.
@@ -81,7 +125,7 @@ def module_level_function(param1, param2=None, *args, **kwargs):
----------
param1 : int
The first parameter.
- param2 : Optional[str]
+ param2 : :obj:`str`, optional
The second parameter.
*args
Variable length argument list.
@@ -113,10 +157,6 @@ def module_level_function(param1, param2=None, *args, **kwargs):
ValueError
If `param2` is equal to `param1`.
-
- .. _PEP 484:
- https://www.python.org/dev/peps/pep-0484/
-
"""
if param1 == param2:
raise ValueError('param1 may not be equal to param2')
@@ -166,7 +206,7 @@ class ExampleError(Exception):
----------
msg : str
Human readable string describing the exception.
- code : Optional[int]
+ code : :obj:`int`, optional
Numeric error code.
Attributes
@@ -194,20 +234,13 @@ class ExampleClass(object):
Properties created with the ``@property`` decorator should be documented
in the property's getter method.
- Attribute and property types -- if given -- should be specified according
- to `PEP 484`_, though `PEP 484`_ conformance isn't required or enforced.
-
Attributes
----------
attr1 : str
Description of `attr1`.
- attr2 : Optional[int]
+ attr2 : :obj:`int`, optional
Description of `attr2`.
-
- .. _PEP 484:
- https://www.python.org/dev/peps/pep-0484/
-
"""
def __init__(self, param1, param2, param3):
@@ -227,10 +260,10 @@ class ExampleClass(object):
----------
param1 : str
Description of `param1`.
- param2 : List[str]
+ param2 : list(str)
Description of `param2`. Multiple
lines are supported.
- param3 : Optional[int]
+ param3 : :obj:`int`, optional
Description of `param3`.
"""
@@ -238,11 +271,11 @@ class ExampleClass(object):
self.attr2 = param2
self.attr3 = param3 #: Doc comment *inline* with attribute
- #: List[str]: Doc comment *before* attribute, with type specified
+ #: list(str): Doc comment *before* attribute, with type specified
self.attr4 = ["attr4"]
self.attr5 = None
- """Optional[str]: Docstring *after* attribute, with type specified."""
+ """str: Docstring *after* attribute, with type specified."""
@property
def readonly_property(self):
@@ -251,8 +284,8 @@ class ExampleClass(object):
@property
def readwrite_property(self):
- """List[str]: Properties with both a getter and setter should only
- be documented in their getter method.
+ """list(str): Properties with both a getter and setter
+ should only be documented in their getter method.
If the setter method contains notable behavior, it should be
mentioned here.
diff --git a/doc/ext/example_numpy.rst b/doc/ext/example_numpy.rst
index a3b41613e..38d3439c8 100644
--- a/doc/ext/example_numpy.rst
+++ b/doc/ext/example_numpy.rst
@@ -9,7 +9,9 @@ Example NumPy Style Python Docstrings
:ref:`example_google`
-Download: :download:`example_numpy.py <example_numpy.py>`
+.. only:: builder_html
+
+ Download: :download:`example_numpy.py <example_numpy.py>`
.. literalinclude:: example_numpy.py
:language: python
diff --git a/doc/ext/inheritance.rst b/doc/ext/inheritance.rst
index dd8d5aa99..bd287aa49 100644
--- a/doc/ext/inheritance.rst
+++ b/doc/ext/inheritance.rst
@@ -40,7 +40,7 @@ It adds this directive:
included.
.. versionchanged:: 1.5
- Added ``caption`` option
+ Added ``caption`` option
New config values are:
diff --git a/doc/ext/napoleon.rst b/doc/ext/napoleon.rst
index 2f2fb4376..ea3e4042f 100644
--- a/doc/ext/napoleon.rst
+++ b/doc/ext/napoleon.rst
@@ -186,11 +186,60 @@ not be mixed. Choose one style for your project and be consistent with it.
* :ref:`example_google`
* :ref:`example_numpy`
- For Python type annotations, see `PEP 484`_.
+
+Type Annotations
+----------------
+
+`PEP 484`_ introduced a standard way to express types in Python code.
+This is an alternative to expressing types directly in docstrings.
+One benefit of expressing types according to `PEP 484`_ is that
+type checkers and IDEs can take advantage of them for static code
+analysis.
+
+Google style with Python 3 type annotations::
+
+ def func(arg1: int, arg2: str) -> bool:
+ """Summary line.
+
+ Extended description of function.
+
+ Args:
+ arg1: Description of arg1
+ arg2: Description of arg2
+
+ Returns:
+ Description of return value
+
+ """
+ return True
+
+Google style with types in docstrings::
+
+ def func(arg1, arg2):
+ """Summary line.
+
+ Extended description of function.
+
+ Args:
+ arg1 (int): Description of arg1
+ arg2 (str): Description of arg2
+
+ Returns:
+ bool: Description of return value
+
+ """
+ return True
+
+.. Note::
+ `Python 2/3 compatible annotations`_ aren't currently
+ supported by Sphinx and won't show up in the docs.
.. _PEP 484:
https://www.python.org/dev/peps/pep-0484/
+.. _Python 2/3 compatible annotations:
+ https://www.python.org/dev/peps/pep-0484/#suggested-syntax-for-python-2-7-and-straddling-code
+
Configuration
=============
@@ -208,6 +257,7 @@ enabled in `conf.py`::
# Napoleon settings
napoleon_google_docstring = True
napoleon_numpy_docstring = True
+ napoleon_include_init_with_doc = False
napoleon_include_private_with_doc = False
napoleon_include_special_with_doc = True
napoleon_use_admonition_for_examples = False
@@ -234,6 +284,23 @@ enabled in `conf.py`::
True to parse `NumPy style`_ docstrings. False to disable support
for NumPy style docstrings. *Defaults to True.*
+.. confval:: napoleon_include_init_with_doc
+
+ True to list ``__init___`` docstrings separately from the class
+ docstring. False to fall back to Sphinx's default behavior, which
+ considers the ``__init___`` docstring as part of the class
+ documentation. *Defaults to False.*
+
+ **If True**::
+
+ def __init__(self):
+ \"\"\"
+ This will be included in the docs because it has a docstring
+ \"\"\"
+
+ def __init__(self):
+ # This will NOT be included in the docs
+
.. confval:: napoleon_include_private_with_doc
True to include private members (like ``_membername``) with docstrings
diff --git a/doc/ext/todo.rst b/doc/ext/todo.rst
index a809bc665..09abfa9b8 100644
--- a/doc/ext/todo.rst
+++ b/doc/ext/todo.rst
@@ -34,6 +34,13 @@ There is also an additional config value:
If this is ``True``, :rst:dir:`todo` and :rst:dir:`todolist` produce output,
else they produce nothing. The default is ``False``.
+.. confval:: todo_emit_warnings
+
+ If this is ``True``, :rst:dir:`todo` emits a warning for each TODO entries.
+ The default is ``False``.
+
+ .. versionadded:: 1.5
+
.. confval:: todo_link_only
If this is ``True``, :rst:dir:`todolist` produce output without file path and line,
@@ -41,3 +48,11 @@ There is also an additional config value:
.. versionadded:: 1.4
+autodoc provides the following an additional event:
+
+.. event:: todo-defined (app, node)
+
+ .. versionadded:: 1.5
+
+ Emitted when a todo is defined. *node* is the defined ``sphinx.ext.todo.todo_node``
+ node.
diff --git a/doc/ext/viewcode.rst b/doc/ext/viewcode.rst
index 5bf8eb033..5823090f6 100644
--- a/doc/ext/viewcode.rst
+++ b/doc/ext/viewcode.rst
@@ -15,6 +15,11 @@ a highlighted version of the source code, and a link will be added to all object
descriptions that leads to the source code of the described object. A link back
from the source to the description will also be inserted.
+This extension works only on HTML related builders like ``html``,
+``applehelp``, ``devhelp``, ``htmlhelp``, ``qthelp`` and so on except
+``singlehtml``. By default ``epub`` builder doesn't
+support this extension (see :confval:`viewcode_enable_epub`).
+
There is an additional config value:
.. confval:: viewcode_import
@@ -34,3 +39,26 @@ There is an additional config value:
main routine is protected by a ``if __name__ == '__main__'`` condition.
.. versionadded:: 1.3
+
+.. confval:: viewcode_enable_epub
+
+ If this is ``True``, viewcode extension is also enabled even if you use
+ epub builders. This extension generates pages outside toctree, but this
+ is not preferred as epub format.
+
+ Until 1.4.x, this extension is always enabled. If you want to generate
+ epub as same as 1.4.x, you should set ``True``, but epub format checker's
+ score becomes worse.
+
+ The default is ``False``.
+
+ .. versionadded:: 1.5
+
+ .. warning::
+
+ Not all epub readers support pages generated by viewcode extension.
+ These readers ignore links to pages are not under toctree.
+
+ Some reader's rendering result are corrupted and
+ `epubcheck <https://github.com/IDPF/epubcheck>`_'s score
+ becomes worse even if the reader supports.
diff --git a/doc/install.rst b/doc/install.rst
index 0ecd73609..a2aeaf9cb 100644
--- a/doc/install.rst
+++ b/doc/install.rst
@@ -135,7 +135,7 @@ install.
.. note::
``pip`` has been contained in the Python official installation after version
- of Python-3.4.0 or Python-2.7.9.
+ of Python-3.4.0 or Python-2.7.9.
Installing Sphinx with pip
diff --git a/doc/installpython.jpg b/doc/installpython.jpg
index b0e458e40..fff4630ae 100644
--- a/doc/installpython.jpg
+++ b/doc/installpython.jpg
Binary files differ
diff --git a/doc/latex.rst b/doc/latex.rst
new file mode 100644
index 000000000..826a715c6
--- /dev/null
+++ b/doc/latex.rst
@@ -0,0 +1,151 @@
+.. highlightlang:: python
+
+.. _latex:
+
+LaTeX customization
+===================
+
+.. module:: latex
+ :synopsis: LaTeX specifics.
+
+The *latex* target does not (yet) benefit from pre-prepared themes like the
+*html* target does (see :doc:`theming`).
+
+There are two principal means of setting up customization:
+
+#. usage of the :ref:`latex-options` as described in :doc:`config`, particularly the
+ various keys of :confval:`latex_elements`, to modify the loaded packages,
+ for example::
+
+ 'fontpkg': '\\usepackage{times}', # can load other font
+ 'fncychap': '\\usepackage[Bjarne]{fncychap}', # can use other option
+
+ .. tip::
+
+ It is not mandatory to load *fncychap*. Naturally, without it and in
+ absence of further customizations, the chapter headings will revert to
+ LaTeX's default for the *report* class.
+
+#. usage of LaTeX ``\renewcommand``, ``\renewenvironment``, ``\setlength``,
+ ``\definecolor`` to modify the defaults from package file :file:`sphinx.sty`
+ and class files :file:`sphinxhowto.cls` and :file:`sphinxmanual.cls`. If such
+ definitions are few, they can be located inside the ``'preamble'`` key of
+ :confval:`latex_elements`. In case of many it may prove more convenient to
+ assemble them into a specialized file :file:`customizedmacros.tex` and use::
+
+ 'preamble': '\\makeatletter\\input{customizedmacros.tex}\\makeatother',
+
+ More advanced LaTeX users will set up a style file
+ :file:`customizedmacros.sty`, which can then be loaded via::
+
+ 'preamble': '\\usepackage{customizedmacros}',
+
+ The :ref:`build configuration file <build-config>` file will then have its variable
+ :confval:`latex_additional_files` appropriately configured, for example::
+
+ latex_additional_files = ["customizedmacros.sty"]
+
+ Such *LaTeX Sphinx theme* files could possibly be contributed in the
+ future by advanced users for wider use.
+
+Let us illustrate here what can be modified by the second method.
+
+- text styling commands (they have one argument): ``\sphinx<foo>`` with
+ ``<foo>`` being one of ``strong``, ``bfcode``, ``email``, ``tablecontinued``,
+ ``titleref``, ``menuselection``, ``accelerator``, ``crossref``, ``termref``,
+ ``optional``. By default and for backwards compatibility the ``\sphinx<foo>``
+ expands to ``\<foo>`` hence the user can choose to customize rather the latter
+ (the non-prefixed macros will be left undefined if option
+ :confval:`latex_keep_old_macro_names` is set to ``False`` in :file:`conf.py`.)
+
+ .. versionchanged:: 1.4.5
+ use of ``\sphinx`` prefixed macro names to limit possibilities of conflict
+ with user added packages. The LaTeX writer uses always the prefixed names.
+- more text styling commands: ``\sphinxstyle<bar>`` with ``<bar>`` one of
+ ``indexentry``, ``indexextra``, ``indexpageref``, ``topictitle``,
+ ``sidebartitle``, ``othertitle``, ``sidebarsubtitle``, ``thead``,
+ ``emphasis``, ``literalemphasis``, ``strong``, ``literalstrong``,
+ ``abbreviation``, ``literalintitle``.
+
+ .. versionadded:: 1.5
+ earlier, the LaTeX writer used hard-coded ``\texttt``, ``\emph``, etc...
+- parameters for paragraph level environments: with ``<foo>`` one of
+ :dudir:`warning`, :dudir:`caution`, :dudir:`attention`,
+ :dudir:`danger`, :dudir:`error`, the colours
+ *sphinx<foo>bordercolor* and *sphinx<foo>bgcolor* can be
+ re-defined using ``\definecolor`` command. The
+ ``\sphinx<foo>border`` is a command (not a LaTeX length) which
+ specifies the thickness of the frame (default ``1pt``) and can be
+ ``\renewcommand`` 'd. The same applies with ``<foo>`` one of
+ :dudir:`note`, :dudir:`hint`, :dudir:`important`, :dudir:`tip`, but
+ the background colour is not implemented by the default environments
+ and the top and bottom rule thickness default is ``0.5pt``.
+
+ .. versionchanged:: 1.5
+ customizability of the parameters for each type of admonition.
+- paragraph level environments: for each admonition as in the previous item, the
+ used environment is named ``sphinx<foo>``. They may be ``\renewenvironment``
+ 'd individually, and must then be defined with one argument (it is the heading
+ of the notice, for example ``Warning:`` for :dudir:`warning` directive, if
+ English is the document language). Their default definitions use either the
+ *sphinxheavybox* (for the first listed directives) or the *sphinxlightbox*
+ environments, configured to use the parameters (colours, border thickness)
+ specific to each type, as mentioned in the previous item.
+
+ .. versionchanged:: 1.5
+ use of public environment names, separate customizability of the parameters.
+- the :dudir:`contents` directive (with ``:local:`` option) and the
+ :dudir:`topic` directive are implemented by environment ``sphinxShadowBox``.
+ Its default definition obeys three LaTeX lengths (not commands) as parameters:
+ ``\sphinxshadowsep`` (distance from contents), ``\sphinxshadowsize`` (width of
+ lateral shadow), ``\sphinxshadowrule`` (thickness of the frame).
+
+ .. versionchanged:: 1.5
+ use of public names for the three lengths. The environment itself was
+ redefined to allow page breaks at release 1.4.2.
+- the literal blocks (:rst:dir:`code-block` directives, etc ...), are
+ implemented using ``sphinxVerbatim`` environment which is a wrapper of
+ ``Verbatim`` environment from package ``fancyvrb.sty``. It adds the handling
+ of the top caption and the wrapping of long lines, and a frame which allows
+ pagebreaks. The LaTeX lengths (not commands) ``\sphinxverbatimsep`` and
+ ``\sphinxverbatimborder`` customize the framing. Inside tables the used
+ environment is ``sphinxVerbatimintable`` (it does not draw a frame, but
+ allows a caption).
+
+ .. versionchanged:: 1.5
+ ``Verbatim`` keeps exact same meaning as in ``fancyvrb.sty`` (meaning
+ which is the one of ``OriginalVerbatim`` too), and custom one is called
+ ``sphinxVerbatim``. Also, earlier version of Sphinx used
+ ``OriginalVerbatim`` inside tables (captions were lost, long code lines
+ were not wrapped), they now use ``sphinxVerbatimintable``.
+ .. versionadded:: 1.5
+ the two customizable lengths, the ``sphinxVerbatimintable``.
+- by default the Sphinx style file ``sphinx.sty`` includes the command
+ ``\fvset{fontsize=\small}`` as part of its configuration of
+ ``fancyvrb.sty``. The user may override this for example via
+ ``\fvset{fontsize=auto}`` which will use for listings the ambient
+ font size. Refer to ``fancyvrb.sty``'s documentation for further keys.
+
+ .. versionadded:: 1.5
+ formerly, the use of ``\small`` for code listings was not customizable.
+- miscellaneous colours: *TitleColor*, *InnerLinkColor*, *OuterLinkColor*,
+ *VerbatimColor* (this is a background colour), *VerbatimBorderColor*.
+- the ``\sphinxAtStartFootnote`` is inserted between footnote numbers and their
+ texts, by default it does ``\mbox{ }``.
+- use ``\sphinxSetHeaderFamily`` to set the font used by headings
+ (default is ``\sffamily\bfseries``).
+
+ .. versionadded:: 1.5
+- the section, subsection, ... headings are set using *titlesec*'s
+ ``\titleformat`` command.
+- for the ``'manual'`` class, the chapter headings can be customized using
+ *fncychap*'s commands ``\ChNameVar``, ``\ChNumVar``, ``\ChTitleVar``. Or, if
+ the loading of this package has been removed from ``'fncychap'`` key, one can
+ use the *titlesec* ``\titleformat`` command.
+
+.. note::
+
+ It is impossible to revert or prevent the loading of a package that results
+ from a ``\usepackage`` executed from inside the :file:`sphinx.sty` style
+ file. Sphinx aims at loading as few packages as are really needed for its
+ default design.
diff --git a/doc/markup/inline.rst b/doc/markup/inline.rst
index 0e825b66a..ae47f820d 100644
--- a/doc/markup/inline.rst
+++ b/doc/markup/inline.rst
@@ -200,6 +200,12 @@ Referencing downloadable files
The ``example.py`` file will be copied to the output directory, and a
suitable link generated to it.
+ Not to show unavailable download links, you should wrap whole paragraphs that
+ have this role::
+
+ .. only:: builder_html
+
+ See :download:`this example script <../example.py>`.
Cross-referencing figures by figure number
------------------------------------------
diff --git a/doc/more.png b/doc/more.png
index a27a0fcba..97553a8b7 100644
--- a/doc/more.png
+++ b/doc/more.png
Binary files differ
diff --git a/doc/pythonorg.png b/doc/pythonorg.png
index 32f0787d1..cf9ccbbdb 100644
--- a/doc/pythonorg.png
+++ b/doc/pythonorg.png
Binary files differ
diff --git a/doc/rest.rst b/doc/rest.rst
index 293b2ea02..7b2b92ddc 100644
--- a/doc/rest.rst
+++ b/doc/rest.rst
@@ -363,8 +363,9 @@ directory on building (e.g. the ``_static`` directory for HTML output.)
Interpretation of image size options (``width`` and ``height``) is as follows:
if the size has no unit or the unit is pixels, the given size will only be
-respected for output channels that support pixels (i.e. not in LaTeX output).
-Other units (like ``pt`` for points) will be used for HTML and LaTeX output.
+respected for output channels that support pixels. Other units (like ``pt``
+for points) will be used for HTML and LaTeX output (the latter replaces ``pt``
+by ``bp`` as this is the TeX unit such that ``72bp=1in``).
Sphinx extends the standard docutils behavior by allowing an asterisk for the
extension::
@@ -386,6 +387,9 @@ Note that image file names should not contain spaces.
.. versionchanged:: 0.6
Image paths can now be absolute.
+.. versionchanged:: 1.5
+ latex target supports pixels (default is ``96px=1in``).
+
Footnotes
---------
diff --git a/doc/themes/agogo.png b/doc/themes/agogo.png
index 453a1f7dc..5a09cb96c 100644
--- a/doc/themes/agogo.png
+++ b/doc/themes/agogo.png
Binary files differ
diff --git a/doc/themes/alabaster.png b/doc/themes/alabaster.png
index 6e02c35ca..4a49c1ad0 100644
--- a/doc/themes/alabaster.png
+++ b/doc/themes/alabaster.png
Binary files differ
diff --git a/doc/themes/bizstyle.png b/doc/themes/bizstyle.png
index 4deae9a79..e19fb6b34 100644
--- a/doc/themes/bizstyle.png
+++ b/doc/themes/bizstyle.png
Binary files differ
diff --git a/doc/themes/classic.png b/doc/themes/classic.png
index 6989ebe9b..3b3c9cbd8 100644
--- a/doc/themes/classic.png
+++ b/doc/themes/classic.png
Binary files differ
diff --git a/doc/themes/fullsize/agogo.png b/doc/themes/fullsize/agogo.png
index bfdba3a17..106a16cea 100644
--- a/doc/themes/fullsize/agogo.png
+++ b/doc/themes/fullsize/agogo.png
Binary files differ
diff --git a/doc/themes/fullsize/alabaster.png b/doc/themes/fullsize/alabaster.png
index 3e026c999..5eca20912 100644
--- a/doc/themes/fullsize/alabaster.png
+++ b/doc/themes/fullsize/alabaster.png
Binary files differ
diff --git a/doc/themes/fullsize/bizstyle.png b/doc/themes/fullsize/bizstyle.png
index d917e2ff2..586064765 100644
--- a/doc/themes/fullsize/bizstyle.png
+++ b/doc/themes/fullsize/bizstyle.png
Binary files differ
diff --git a/doc/themes/fullsize/classic.png b/doc/themes/fullsize/classic.png
index 9c00f6899..269dab22f 100644
--- a/doc/themes/fullsize/classic.png
+++ b/doc/themes/fullsize/classic.png
Binary files differ
diff --git a/doc/themes/fullsize/haiku.png b/doc/themes/fullsize/haiku.png
index 8d807f4e1..707d2bfec 100644
--- a/doc/themes/fullsize/haiku.png
+++ b/doc/themes/fullsize/haiku.png
Binary files differ
diff --git a/doc/themes/fullsize/nature.png b/doc/themes/fullsize/nature.png
index 02d8743b3..00730c0a5 100644
--- a/doc/themes/fullsize/nature.png
+++ b/doc/themes/fullsize/nature.png
Binary files differ
diff --git a/doc/themes/fullsize/pyramid.png b/doc/themes/fullsize/pyramid.png
index 961cb896c..3b9d04d13 100644
--- a/doc/themes/fullsize/pyramid.png
+++ b/doc/themes/fullsize/pyramid.png
Binary files differ
diff --git a/doc/themes/fullsize/scrolls.png b/doc/themes/fullsize/scrolls.png
index 4e5c45f21..8a1c1faf5 100644
--- a/doc/themes/fullsize/scrolls.png
+++ b/doc/themes/fullsize/scrolls.png
Binary files differ
diff --git a/doc/themes/fullsize/sphinx_rtd_theme.png b/doc/themes/fullsize/sphinx_rtd_theme.png
index 4a3d74c88..95cff4ccd 100644
--- a/doc/themes/fullsize/sphinx_rtd_theme.png
+++ b/doc/themes/fullsize/sphinx_rtd_theme.png
Binary files differ
diff --git a/doc/themes/fullsize/sphinxdoc.png b/doc/themes/fullsize/sphinxdoc.png
index b74633452..eb498e3e8 100644
--- a/doc/themes/fullsize/sphinxdoc.png
+++ b/doc/themes/fullsize/sphinxdoc.png
Binary files differ
diff --git a/doc/themes/fullsize/traditional.png b/doc/themes/fullsize/traditional.png
index da69efe12..07ad00875 100644
--- a/doc/themes/fullsize/traditional.png
+++ b/doc/themes/fullsize/traditional.png
Binary files differ
diff --git a/doc/themes/haiku.png b/doc/themes/haiku.png
index 78a2570c4..4530debb9 100644
--- a/doc/themes/haiku.png
+++ b/doc/themes/haiku.png
Binary files differ
diff --git a/doc/themes/nature.png b/doc/themes/nature.png
index cbe773d5c..ad39b32b7 100644
--- a/doc/themes/nature.png
+++ b/doc/themes/nature.png
Binary files differ
diff --git a/doc/themes/pyramid.png b/doc/themes/pyramid.png
index eb13cd5f2..72749dd6b 100644
--- a/doc/themes/pyramid.png
+++ b/doc/themes/pyramid.png
Binary files differ
diff --git a/doc/themes/scrolls.png b/doc/themes/scrolls.png
index 30ccc8d49..1a117379f 100644
--- a/doc/themes/scrolls.png
+++ b/doc/themes/scrolls.png
Binary files differ
diff --git a/doc/themes/sphinx_rtd_theme.png b/doc/themes/sphinx_rtd_theme.png
index e13f52b04..7c3b7ae05 100644
--- a/doc/themes/sphinx_rtd_theme.png
+++ b/doc/themes/sphinx_rtd_theme.png
Binary files differ
diff --git a/doc/themes/sphinxdoc.png b/doc/themes/sphinxdoc.png
index 31512d8d8..587363e61 100644
--- a/doc/themes/sphinxdoc.png
+++ b/doc/themes/sphinxdoc.png
Binary files differ
diff --git a/doc/themes/traditional.png b/doc/themes/traditional.png
index 5ff44f869..9820fd0ea 100644
--- a/doc/themes/traditional.png
+++ b/doc/themes/traditional.png
Binary files differ
diff --git a/doc/theming.rst b/doc/theming.rst
index df0755f1f..ee45df52d 100644
--- a/doc/theming.rst
+++ b/doc/theming.rst
@@ -81,6 +81,8 @@ that has to return the directory with themes in it::
Builtin themes
--------------
+.. cssclass:: longtable
+
+--------------------+--------------------+
| **Theme overview** | |
+--------------------+--------------------+
diff --git a/doc/translation.png b/doc/translation.png
index 347e287f6..11f3d02cd 100644
--- a/doc/translation.png
+++ b/doc/translation.png
Binary files differ
diff --git a/doc/tutorial.rst b/doc/tutorial.rst
index 385746f72..bced21ade 100644
--- a/doc/tutorial.rst
+++ b/doc/tutorial.rst
@@ -300,12 +300,17 @@ features of intersphinx.
More topics to be covered
-------------------------
-- Other extensions (math, viewcode, doctest)
+- :doc:`Other extensions <extensions>`:
+
+ * :doc:`ext/math`,
+ * :doc:`ext/viewcode`,
+ * :doc:`ext/doctest`,
+ * ...
- Static files
-- Selecting a theme
-- Templating
+- :doc:`Selecting a theme <theming>`
+- :ref:`Templating <templating>`
- Using extensions
-- Writing extensions
+- :ref:`Writing extensions <dev-extensions>`
.. rubric:: Footnotes
diff --git a/setup.cfg b/setup.cfg
index 2d2f3b535..a65719461 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -25,5 +25,5 @@ universal = 1
[flake8]
max-line-length=95
-ignore=E113,E116,E221,E226,E241,E251
-exclude=ez_setup.py,utils/*,tests/*,build/*,sphinx/search/*,sphinx/pycode/pgen2/*
+ignore=E113,E116,E221,E226,E241,E251,E901
+exclude=tests/*,build/*,sphinx/search/*,sphinx/pycode/pgen2/*,doc/ext/example*.py
diff --git a/setup.py b/setup.py
index 3d792b2dc..c1aa346ba 100644
--- a/setup.py
+++ b/setup.py
@@ -64,6 +64,7 @@ extras_require = {
'nose',
'mock', # it would be better for 'test:python_version in "2.6,2.7"'
'simplejson', # better: 'test:platform_python_implementation=="PyPy"'
+ 'html5lib',
],
}
@@ -137,11 +138,8 @@ else:
domain + '.js'))
for js_file, (locale, po_file) in zip(js_files, po_files):
- infile = open(po_file, 'r')
- try:
+ with open(po_file, 'r') as infile:
catalog = read_po(infile, locale)
- finally:
- infile.close()
if catalog.fuzzy and not self.use_fuzzy:
continue
@@ -158,8 +156,7 @@ else:
msgid = msgid[0]
jscatalog[msgid] = message.string
- outfile = open(js_file, 'wb')
- try:
+ with open(js_file, 'wb') as outfile:
outfile.write('Documentation.addTranslations(')
dump(dict(
messages=jscatalog,
@@ -167,8 +164,6 @@ else:
locale=str(catalog.locale)
), outfile, sort_keys=True)
outfile.write(');')
- finally:
- outfile.close()
cmdclass['compile_catalog'] = compile_catalog_plusjs
diff --git a/sphinx/application.py b/sphinx/application.py
index e82719d77..d8cae8435 100644
--- a/sphinx/application.py
+++ b/sphinx/application.py
@@ -32,17 +32,16 @@ from sphinx.roles import XRefRole
from sphinx.config import Config
from sphinx.errors import SphinxError, SphinxWarning, ExtensionError, \
VersionRequirementError, ConfigError
-from sphinx.domains import ObjType, BUILTIN_DOMAINS
+from sphinx.domains import ObjType
from sphinx.domains.std import GenericObject, Target, StandardDomain
-from sphinx.builders import BUILTIN_BUILDERS
from sphinx.environment import BuildEnvironment
from sphinx.io import SphinxStandaloneReader
-from sphinx.util import pycompat # noqa: imported for side-effects
+from sphinx.util import pycompat # noqa: F401
from sphinx.util import import_object
from sphinx.util.tags import Tags
from sphinx.util.osutil import ENOENT
from sphinx.util.logging import is_suppressed_warning
-from sphinx.util.console import bold, lightgray, darkgray, darkgreen, \
+from sphinx.util.console import bold, lightgray, darkgray, darkred, darkgreen, \
term_width_line
from sphinx.util.i18n import find_catalog_source_files
@@ -65,10 +64,44 @@ events = {
'html-page-context': 'pagename, context, doctree or None',
'build-finished': 'exception',
}
+builtin_extensions = (
+ 'sphinx.builders.applehelp',
+ 'sphinx.builders.changes',
+ 'sphinx.builders.epub',
+ 'sphinx.builders.epub3',
+ 'sphinx.builders.devhelp',
+ 'sphinx.builders.dummy',
+ 'sphinx.builders.gettext',
+ 'sphinx.builders.html',
+ 'sphinx.builders.htmlhelp',
+ 'sphinx.builders.latex',
+ 'sphinx.builders.linkcheck',
+ 'sphinx.builders.manpage',
+ 'sphinx.builders.qthelp',
+ 'sphinx.builders.texinfo',
+ 'sphinx.builders.text',
+ 'sphinx.builders.websupport',
+ 'sphinx.builders.xml',
+ 'sphinx.domains.c',
+ 'sphinx.domains.cpp',
+ 'sphinx.domains.javascript',
+ 'sphinx.domains.python',
+ 'sphinx.domains.rst',
+ 'sphinx.domains.std',
+ 'sphinx.directives',
+ 'sphinx.directives.code',
+ 'sphinx.directives.other',
+ 'sphinx.directives.patches',
+ 'sphinx.roles',
+)
CONFIG_FILENAME = 'conf.py'
ENV_PICKLE_FILENAME = 'environment.pickle'
+# list of deprecated extensions. Keys are extension name.
+# Values are Sphinx version that merge the extension.
+EXTENSION_BLACKLIST = {"sphinxjp.themecore": "1.2"}
+
class Sphinx(object):
@@ -83,9 +116,9 @@ class Sphinx(object):
self._additional_source_parsers = {}
self._listeners = {}
self._setting_up_extension = ['?']
- self.domains = BUILTIN_DOMAINS.copy()
+ self.domains = {}
self.buildername = buildername
- self.builderclasses = BUILTIN_BUILDERS.copy()
+ self.builderclasses = {}
self.builder = None
self.env = None
self.enumerable_nodes = {}
@@ -148,6 +181,10 @@ class Sphinx(object):
if self.confdir is None:
self.confdir = self.srcdir
+ # load all built-in extension modules
+ for extension in builtin_extensions:
+ self.setup_extension(extension)
+
# extension loading support for alabaster theme
# self.config.html_theme is not set from conf.py at here
# for now, sphinx always load a 'alabaster' extension.
@@ -188,6 +225,10 @@ class Sphinx(object):
'version %s and therefore cannot be built with the '
'loaded version (%s).' % (extname, needs_ver, has_ver))
+ # check primary_domain if requested
+ if self.config.primary_domain and self.config.primary_domain not in self.domains:
+ self.warn('primary_domain %r not found, ignored.' % self.config.primary_domain)
+
# set up translation infrastructure
self._init_i18n()
# check all configuration values for permissible types
@@ -235,8 +276,8 @@ class Sphinx(object):
def _init_env(self, freshenv):
if freshenv:
- self.env = BuildEnvironment(self.srcdir, self.doctreedir,
- self.config)
+ self.env = BuildEnvironment(self.srcdir, self.doctreedir, self.config)
+ self.env.set_warnfunc(self.warn)
self.env.find_files(self.config)
for domain in self.domains.keys():
self.env.domains[domain] = self.domains[domain](self.env)
@@ -245,6 +286,7 @@ class Sphinx(object):
self.info(bold('loading pickled environment... '), nonl=True)
self.env = BuildEnvironment.frompickle(
self.srcdir, self.config, path.join(self.doctreedir, ENV_PICKLE_FILENAME))
+ self.env.set_warnfunc(self.warn)
self.env.domains = {}
for domain in self.domains.keys():
# this can raise if the data version doesn't fit
@@ -257,8 +299,6 @@ class Sphinx(object):
self.info('failed: %s' % err)
return self._init_env(freshenv=True)
- self.env.set_warnfunc(self.warn)
-
def _init_builder(self, buildername):
if buildername is None:
print('No builder selected, using default: html', file=self._status)
@@ -267,11 +307,6 @@ class Sphinx(object):
raise SphinxError('Builder name %s not registered' % buildername)
builderclass = self.builderclasses[buildername]
- if isinstance(builderclass, tuple):
- # builtin builder
- mod, cls = builderclass
- builderclass = getattr(
- __import__('sphinx.builders.' + mod, None, None, [cls]), cls)
self.builder = builderclass(self)
self.emit('builder-inited')
@@ -326,7 +361,8 @@ class Sphinx(object):
wfile.flush()
self.messagelog.append(message)
- def warn(self, message, location=None, prefix='WARNING: ', type=None, subtype=None):
+ def warn(self, message, location=None, prefix='WARNING: ',
+ type=None, subtype=None, colorfunc=darkred):
"""Emit a warning.
If *location* is given, it should either be a tuple of (docname, lineno)
@@ -356,7 +392,7 @@ class Sphinx(object):
if self.warningiserror:
raise SphinxWarning(warntext)
self._warncount += 1
- self._log(warntext, self._warning, True)
+ self._log(colorfunc(warntext), self._warning, True)
def info(self, message='', nonl=False):
"""Emit an informational message.
@@ -460,6 +496,11 @@ class Sphinx(object):
self.debug('[app] setting up extension: %r', extension)
if extension in self._extensions:
return
+ if extension in EXTENSION_BLACKLIST:
+ self.warn('the extension %r was already merged with Sphinx since version %s; '
+ 'this extension is ignored.' % (
+ extension, EXTENSION_BLACKLIST[extension]))
+ return
self._setting_up_extension.append(extension)
try:
mod = __import__(extension, None, None, ['setup'])
@@ -557,13 +598,9 @@ class Sphinx(object):
raise ExtensionError('Builder class %s has no "name" attribute'
% builder)
if builder.name in self.builderclasses:
- if isinstance(self.builderclasses[builder.name], tuple):
- raise ExtensionError('Builder %r is a builtin builder' %
- builder.name)
- else:
- raise ExtensionError(
- 'Builder %r already exists (in module %s)' % (
- builder.name, self.builderclasses[builder.name].__module__))
+ raise ExtensionError(
+ 'Builder %r already exists (in module %s)' % (
+ builder.name, self.builderclasses[builder.name].__module__))
self.builderclasses[builder.name] = builder
def add_config_value(self, name, default, rebuild, types=()):
@@ -764,8 +801,7 @@ class Sphinx(object):
def add_latex_package(self, packagename, options=None):
self.debug('[app] adding latex package: %r', packagename)
- from sphinx.builders.latex import LaTeXBuilder
- LaTeXBuilder.usepackages.append((packagename, options))
+ self.builder.usepackages.append((packagename, options))
def add_lexer(self, alias, lexer):
self.debug('[app] adding lexer: %r', (alias, lexer))
diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py
index 8863050ba..fe0c9c665 100644
--- a/sphinx/builders/__init__.py
+++ b/sphinx/builders/__init__.py
@@ -451,29 +451,3 @@ class Builder(object):
except AttributeError:
optname = '%s_%s' % (default, option)
return getattr(self.config, optname)
-
-BUILTIN_BUILDERS = {
- 'dummy': ('dummy', 'DummyBuilder'),
- 'html': ('html', 'StandaloneHTMLBuilder'),
- 'dirhtml': ('html', 'DirectoryHTMLBuilder'),
- 'singlehtml': ('html', 'SingleFileHTMLBuilder'),
- 'pickle': ('html', 'PickleHTMLBuilder'),
- 'json': ('html', 'JSONHTMLBuilder'),
- 'web': ('html', 'PickleHTMLBuilder'),
- 'htmlhelp': ('htmlhelp', 'HTMLHelpBuilder'),
- 'devhelp': ('devhelp', 'DevhelpBuilder'),
- 'qthelp': ('qthelp', 'QtHelpBuilder'),
- 'applehelp': ('applehelp', 'AppleHelpBuilder'),
- 'epub': ('epub', 'EpubBuilder'),
- 'epub3': ('epub3', 'Epub3Builder'),
- 'latex': ('latex', 'LaTeXBuilder'),
- 'text': ('text', 'TextBuilder'),
- 'man': ('manpage', 'ManualPageBuilder'),
- 'texinfo': ('texinfo', 'TexinfoBuilder'),
- 'changes': ('changes', 'ChangesBuilder'),
- 'linkcheck': ('linkcheck', 'CheckExternalLinksBuilder'),
- 'websupport': ('websupport', 'WebSupportBuilder'),
- 'gettext': ('gettext', 'MessageCatalogBuilder'),
- 'xml': ('xml', 'XMLBuilder'),
- 'pseudoxml': ('xml', 'PseudoXMLBuilder'),
-}
diff --git a/sphinx/builders/applehelp.py b/sphinx/builders/applehelp.py
index d3ad861dc..7db086953 100644
--- a/sphinx/builders/applehelp.py
+++ b/sphinx/builders/applehelp.py
@@ -13,14 +13,16 @@ from __future__ import print_function
import codecs
import pipes
-from os import path
+from os import path, environ
+import shlex
from sphinx.builders.html import StandaloneHTMLBuilder
-from sphinx.util import copy_static_entry
-from sphinx.util.osutil import copyfile, ensuredir
+from sphinx.config import string_classes
+from sphinx.util.osutil import copyfile, ensuredir, make_filename
from sphinx.util.console import bold
+from sphinx.util.fileutil import copy_asset
from sphinx.util.pycompat import htmlescape
-from sphinx.util.matching import compile_matchers
+from sphinx.util.matching import Matcher
from sphinx.errors import SphinxError
import plistlib
@@ -84,6 +86,7 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
super(AppleHelpBuilder, self).init()
# the output files for HTML help must be .html only
self.out_suffix = '.html'
+ self.link_suffix = '.html'
if self.config.applehelp_bundle_id is None:
raise SphinxError('You must set applehelp_bundle_id before '
@@ -104,17 +107,15 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
self.finish_tasks.add_task(self.build_helpbook)
def copy_localized_files(self):
- source_dir = path.join(self.confdir,
- self.config.applehelp_locale + '.lproj')
+ source_dir = path.join(self.confdir, self.config.applehelp_locale + '.lproj')
target_dir = self.outdir
if path.isdir(source_dir):
self.info(bold('copying localized files... '), nonl=True)
- ctx = self.globalcontext.copy()
- matchers = compile_matchers(self.config.exclude_patterns)
- copy_static_entry(source_dir, target_dir, self, ctx,
- exclude_matchers=matchers)
+ excluded = Matcher(self.config.exclude_patterns + ['**/.*'])
+ copy_asset(source_dir, target_dir, excluded,
+ context=self.globalcontext, renderer=self.templates)
self.info('done')
@@ -213,16 +214,19 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
self.warn('you will need to index this help book with:\n %s'
% (' '.join([pipes.quote(arg) for arg in args])))
else:
- p = subprocess.Popen(args,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
+ try:
+ p = subprocess.Popen(args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
- output = p.communicate()[0]
+ output = p.communicate()[0]
- if p.returncode != 0:
- raise AppleHelpIndexerFailed(output)
- else:
- self.info('done')
+ if p.returncode != 0:
+ raise AppleHelpIndexerFailed(output)
+ else:
+ self.info('done')
+ except OSError:
+ raise AppleHelpIndexerFailed('Command not found: %s' % args[0])
# If we've been asked to, sign the bundle
if self.config.applehelp_codesign_identity:
@@ -244,13 +248,48 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
self.warn('you will need to sign this help book with:\n %s'
% (' '.join([pipes.quote(arg) for arg in args])))
else:
- p = subprocess.Popen(args,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
-
- output = p.communicate()[0]
-
- if p.returncode != 0:
- raise AppleHelpCodeSigningFailed(output)
- else:
- self.info('done')
+ try:
+ p = subprocess.Popen(args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+
+ output = p.communicate()[0]
+
+ if p.returncode != 0:
+ raise AppleHelpCodeSigningFailed(output)
+ else:
+ self.info('done')
+ except OSError:
+ raise AppleHelpCodeSigningFailed('Command not found: %s' % args[0])
+
+
+def setup(app):
+ app.setup_extension('sphinx.builders.html')
+ app.add_builder(AppleHelpBuilder)
+
+ app.add_config_value('applehelp_bundle_name',
+ lambda self: make_filename(self.project), 'applehelp')
+ app.add_config_value('applehelp_bundle_id', None, 'applehelp', string_classes)
+ app.add_config_value('applehelp_dev_region', 'en-us', 'applehelp')
+ app.add_config_value('applehelp_bundle_version', '1', 'applehelp')
+ app.add_config_value('applehelp_icon', None, 'applehelp', string_classes)
+ app.add_config_value('applehelp_kb_product',
+ lambda self: '%s-%s' % (make_filename(self.project), self.release),
+ 'applehelp')
+ app.add_config_value('applehelp_kb_url', None, 'applehelp', string_classes)
+ app.add_config_value('applehelp_remote_url', None, 'applehelp', string_classes)
+ app.add_config_value('applehelp_index_anchors', False, 'applehelp', string_classes)
+ app.add_config_value('applehelp_min_term_length', None, 'applehelp', string_classes)
+ app.add_config_value('applehelp_stopwords',
+ lambda self: self.language or 'en', 'applehelp')
+ app.add_config_value('applehelp_locale', lambda self: self.language or 'en', 'applehelp')
+ app.add_config_value('applehelp_title', lambda self: self.project + ' Help', 'applehelp')
+ app.add_config_value('applehelp_codesign_identity',
+ lambda self: environ.get('CODE_SIGN_IDENTITY', None),
+ 'applehelp'),
+ app.add_config_value('applehelp_codesign_flags',
+ lambda self: shlex.split(environ.get('OTHER_CODE_SIGN_FLAGS', '')),
+ 'applehelp'),
+ app.add_config_value('applehelp_indexer_path', '/usr/bin/hiutil', 'applehelp')
+ app.add_config_value('applehelp_codesign_path', '/usr/bin/codesign', 'applehelp')
+ app.add_config_value('applehelp_disable_external_tools', False, None)
diff --git a/sphinx/builders/changes.py b/sphinx/builders/changes.py
index ed9edc403..1bccb67d9 100644
--- a/sphinx/builders/changes.py
+++ b/sphinx/builders/changes.py
@@ -15,12 +15,12 @@ from os import path
from six import iteritems
from sphinx import package_dir
-from sphinx.util import copy_static_entry
from sphinx.locale import _
from sphinx.theming import Theme
from sphinx.builders import Builder
from sphinx.util.osutil import ensuredir, os_path
from sphinx.util.console import bold
+from sphinx.util.fileutil import copy_asset_file
from sphinx.util.pycompat import htmlescape
@@ -138,12 +138,10 @@ class ChangesBuilder(Builder):
f.write(self.templates.render('changes/rstsource.html', ctx))
themectx = dict(('theme_' + key, val) for (key, val) in
iteritems(self.theme.get_options({})))
- copy_static_entry(path.join(package_dir, 'themes', 'default',
- 'static', 'default.css_t'),
- self.outdir, self, themectx)
- copy_static_entry(path.join(package_dir, 'themes', 'basic',
- 'static', 'basic.css'),
- self.outdir, self)
+ copy_asset_file(path.join(package_dir, 'themes', 'default', 'static', 'default.css_t'),
+ self.outdir, context=themectx, renderer=self.templates)
+ copy_asset_file(path.join(package_dir, 'themes', 'basic', 'static', 'basic.css'),
+ self.outdir)
def hl(self, text, version):
text = htmlescape(text)
@@ -154,3 +152,7 @@ class ChangesBuilder(Builder):
def finish(self):
pass
+
+
+def setup(app):
+ app.add_builder(ChangesBuilder)
diff --git a/sphinx/builders/devhelp.py b/sphinx/builders/devhelp.py
index eb3e997d8..0f88e9f38 100644
--- a/sphinx/builders/devhelp.py
+++ b/sphinx/builders/devhelp.py
@@ -18,6 +18,7 @@ from os import path
from docutils import nodes
from sphinx import addnodes
+from sphinx.util.osutil import make_filename
from sphinx.builders.html import StandaloneHTMLBuilder
try:
@@ -59,6 +60,7 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
def init(self):
StandaloneHTMLBuilder.init(self)
self.out_suffix = '.html'
+ self.link_suffix = '.html'
def handle_finish(self):
self.build_devhelp(self.outdir, self.config.devhelp_basename)
@@ -129,3 +131,10 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
# Dump the XML file
with comp_open(path.join(outdir, outname + '.devhelp'), 'w') as f:
tree.write(f, 'utf-8')
+
+
+def setup(app):
+ app.setup_extension('sphinx.builders.html')
+ app.add_builder(DevhelpBuilder)
+
+ app.add_config_value('devhelp_basename', lambda self: make_filename(self.project), None)
diff --git a/sphinx/builders/dummy.py b/sphinx/builders/dummy.py
index 75b834c2b..b119d9687 100644
--- a/sphinx/builders/dummy.py
+++ b/sphinx/builders/dummy.py
@@ -34,3 +34,7 @@ class DummyBuilder(Builder):
def finish(self):
pass
+
+
+def setup(app):
+ app.add_builder(DummyBuilder)
diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py
index 349574ae0..ffe33e1ed 100644
--- a/sphinx/builders/epub.py
+++ b/sphinx/builders/epub.py
@@ -29,7 +29,7 @@ from docutils import nodes
from sphinx import addnodes
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.util.i18n import format_date
-from sphinx.util.osutil import ensuredir, copyfile, EEXIST
+from sphinx.util.osutil import ensuredir, copyfile, make_filename, EEXIST
from sphinx.util.smartypants import sphinx_smarty_pants as ssp
from sphinx.util.console import brown
@@ -113,7 +113,7 @@ COVER_TEMPLATE = u'''\
<meta name="cover" content="%(cover)s"/>
'''
-COVERPAGE_NAME = u'epub-cover.html'
+COVERPAGE_NAME = u'epub-cover.xhtml'
FILE_TEMPLATE = u'''\
<item id="%(id)s"
@@ -128,6 +128,10 @@ GUIDE_TEMPLATE = u'''\
TOCTREE_TEMPLATE = u'toctree-l%d'
+DOCTYPE = u'''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+'''
+
LINK_TARGET_TEMPLATE = u' [%(uri)s]'
FOOTNOTE_LABEL_TEMPLATE = u'#%d'
@@ -143,7 +147,7 @@ GUIDE_TITLES = {
}
MEDIA_TYPES = {
- '.html': 'application/xhtml+xml',
+ '.xhtml': 'application/xhtml+xml',
'.css': 'text/css',
'.png': 'image/png',
'.gif': 'image/gif',
@@ -152,6 +156,7 @@ MEDIA_TYPES = {
'.jpeg': 'image/jpeg',
'.otf': 'application/x-font-otf',
'.ttf': 'application/x-font-ttf',
+ '.woff': 'application/font-woff',
}
VECTOR_GRAPHICS_EXTENSIONS = ('.svg',)
@@ -183,6 +188,11 @@ class EpubBuilder(StandaloneHTMLBuilder):
add_permalinks = False
# don't add sidebar etc.
embedded = True
+ # disable download role
+ download_support = False
+
+ # don't generate search index or include search page
+ search = False
mimetype_template = MIMETYPE_TEMPLATE
container_template = CONTAINER_TEMPLATE
@@ -197,6 +207,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
spine_template = SPINE_TEMPLATE
guide_template = GUIDE_TEMPLATE
toctree_template = TOCTREE_TEMPLATE
+ doctype = DOCTYPE
link_target_template = LINK_TARGET_TEMPLATE
css_link_target_class = CSS_LINK_TARGET_CLASS
guide_titles = GUIDE_TITLES
@@ -206,7 +217,8 @@ class EpubBuilder(StandaloneHTMLBuilder):
def init(self):
StandaloneHTMLBuilder.init(self)
# the output files for epub must be .html only
- self.out_suffix = '.html'
+ self.out_suffix = '.xhtml'
+ self.link_suffix = '.xhtml'
self.playorder = 0
self.tocid = 0
@@ -276,7 +288,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
"""
refnodes.insert(0, {
'level': 1,
- 'refuri': self.esc(self.config.master_doc + '.html'),
+ 'refuri': self.esc(self.config.master_doc + self.out_suffix),
'text': ssp(self.esc(
self.env.titles[self.config.master_doc].astext()))
})
@@ -471,6 +483,9 @@ class EpubBuilder(StandaloneHTMLBuilder):
else:
super(EpubBuilder, self).copy_image_files()
+ def copy_download_files(self):
+ pass
+
def handle_page(self, pagename, addctx, templatename='page.html',
outfilename=None, event_arg=None):
"""Create a rendered page.
@@ -480,6 +495,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
"""
if pagename.startswith('genindex'):
self.fix_genindex(addctx['genindexentries'])
+ addctx['doctype'] = self.doctype
StandaloneHTMLBuilder.handle_page(self, pagename, addctx, templatename,
outfilename, event_arg)
@@ -760,3 +776,33 @@ class EpubBuilder(StandaloneHTMLBuilder):
fp = path.join(outdir, file)
epub.write(fp, file, zipfile.ZIP_DEFLATED)
epub.close()
+
+
+def setup(app):
+ app.setup_extension('sphinx.builders.html')
+ app.add_builder(EpubBuilder)
+
+ # config values
+ app.add_config_value('epub_basename', lambda self: make_filename(self.project), None)
+ app.add_config_value('epub_theme', 'epub', 'html')
+ app.add_config_value('epub_theme_options', {}, 'html')
+ app.add_config_value('epub_title', lambda self: self.html_title, 'html')
+ app.add_config_value('epub_author', 'unknown', 'html')
+ app.add_config_value('epub_language', lambda self: self.language or 'en', 'html')
+ app.add_config_value('epub_publisher', 'unknown', 'html')
+ app.add_config_value('epub_copyright', lambda self: self.copyright, 'html')
+ app.add_config_value('epub_identifier', 'unknown', 'html')
+ app.add_config_value('epub_scheme', 'unknown', 'html')
+ app.add_config_value('epub_uid', 'unknown', 'env')
+ app.add_config_value('epub_cover', (), 'env')
+ app.add_config_value('epub_guide', (), 'env')
+ app.add_config_value('epub_pre_files', [], 'env')
+ app.add_config_value('epub_post_files', [], 'env')
+ app.add_config_value('epub_exclude_files', [], 'env')
+ app.add_config_value('epub_tocdepth', 3, 'env')
+ app.add_config_value('epub_tocdup', True, 'env')
+ app.add_config_value('epub_tocscope', 'default', 'env')
+ app.add_config_value('epub_fix_images', False, 'env')
+ app.add_config_value('epub_max_image_width', 0, 'env')
+ app.add_config_value('epub_show_urls', 'inline', 'html')
+ app.add_config_value('epub_use_index', lambda self: self.html_use_index, 'html')
diff --git a/sphinx/builders/epub3.py b/sphinx/builders/epub3.py
index b243486f6..fc15a1c46 100644
--- a/sphinx/builders/epub3.py
+++ b/sphinx/builders/epub3.py
@@ -13,6 +13,7 @@
import codecs
from os import path
+from sphinx.config import string_classes
from sphinx.builders.epub import EpubBuilder
@@ -73,7 +74,6 @@ PACKAGE_DOC_TEMPLATE = u'''\
%(files)s
</manifest>
<spine toc="ncx" page-progression-direction="%(page_progression_direction)s">
- <itemref idref="nav" />
%(spine)s
</spine>
<guide>
@@ -82,6 +82,9 @@ PACKAGE_DOC_TEMPLATE = u'''\
</package>
'''
+DOCTYPE = u'''<!DOCTYPE html>
+'''
+
# The epub3 publisher
@@ -99,6 +102,7 @@ class Epub3Builder(EpubBuilder):
navlist_template = NAVLIST_TEMPLATE
navlist_indent = NAVLIST_INDENT
content_template = PACKAGE_DOC_TEMPLATE
+ doctype = DOCTYPE
# Finish by building the epub file
def handle_finish(self):
@@ -209,3 +213,12 @@ class Epub3Builder(EpubBuilder):
# Add nav.xhtml to epub file
self.files.append(outname)
+
+
+def setup(app):
+ app.setup_extension('sphinx.builders.epub')
+ app.add_builder(Epub3Builder)
+
+ app.add_config_value('epub3_description', '', 'epub3', string_classes)
+ app.add_config_value('epub3_contributor', 'unknown', 'epub3', string_classes)
+ app.add_config_value('epub3_page_progression_direction', 'ltr', 'epub3', string_classes)
diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py
index c8f4dab4f..aa9400575 100644
--- a/sphinx/builders/gettext.py
+++ b/sphinx/builders/gettext.py
@@ -135,7 +135,7 @@ tzdelta = datetime.fromtimestamp(timestamp) - \
source_date_epoch = getenv('SOURCE_DATE_EPOCH')
if source_date_epoch is not None:
timestamp = float(source_date_epoch)
- tzdelta = 0
+ tzdelta = timedelta(0)
class LocalTimeZone(tzinfo):
@@ -233,3 +233,13 @@ class MessageCatalogBuilder(I18nBuilder):
replace('"', r'\"'). \
replace('\n', '\\n"\n"')
pofile.write('msgid "%s"\nmsgstr ""\n\n' % message)
+
+
+def setup(app):
+ app.add_builder(MessageCatalogBuilder)
+
+ app.add_config_value('gettext_compact', True, 'gettext')
+ app.add_config_value('gettext_location', True, 'gettext')
+ app.add_config_value('gettext_uuid', False, 'gettext')
+ app.add_config_value('gettext_auto_build', True, 'env')
+ app.add_config_value('gettext_additional_targets', [], 'env')
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index 63ccdd66c..2cb12609b 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -27,13 +27,15 @@ from docutils.frontend import OptionParser
from docutils.readers.doctree import Reader as DoctreeReader
from sphinx import package_dir, __display_version__
-from sphinx.util import jsonimpl, copy_static_entry, copy_extra_entry
+from sphinx.util import jsonimpl
from sphinx.util.i18n import format_date
from sphinx.util.osutil import SEP, os_path, relative_uri, ensuredir, \
movefile, copyfile
from sphinx.util.nodes import inline_all_toctrees
-from sphinx.util.matching import patmatch, compile_matchers
-from sphinx.locale import _
+from sphinx.util.fileutil import copy_asset
+from sphinx.util.matching import patmatch, Matcher, DOTFILES
+from sphinx.config import string_classes
+from sphinx.locale import _, l_
from sphinx.search import js_index
from sphinx.theming import Theme
from sphinx.builders import Builder
@@ -80,6 +82,7 @@ class StandaloneHTMLBuilder(Builder):
add_permalinks = True
embedded = False # for things like HTML help or Qt help: suppresses sidebar
search = True # for things like HTML help and Apple help: suppress search
+ download_support = True # enable download role
# This is a class attribute because it is mutated by Sphinx.add_javascript.
script_files = ['_static/jquery.js', '_static/underscore.js',
@@ -339,6 +342,7 @@ class StandaloneHTMLBuilder(Builder):
show_sphinx = self.config.html_show_sphinx,
has_source = self.config.html_copy_source,
show_source = self.config.html_show_sourcelink,
+ sourcelink_suffix = self.config.html_sourcelink_suffix,
file_suffix = self.out_suffix,
script_files = self.script_files,
language = self.config.language,
@@ -402,15 +406,21 @@ class StandaloneHTMLBuilder(Builder):
# title rendered as HTML
title = self.env.longtitles.get(docname)
title = title and self.render_partial(title)['title'] or ''
+
+ # Suffix for the document
+ source_suffix = path.splitext(self.env.doc2path(docname))[1]
+
# the name for the copied source
- sourcename = self.config.html_copy_source and docname + '.txt' or ''
+ if self.config.html_copy_source:
+ sourcename = docname + source_suffix
+ if source_suffix != self.config.html_sourcelink_suffix:
+ sourcename += self.config.html_sourcelink_suffix
+ else:
+ sourcename = ''
# metadata for the document
meta = self.env.metadata.get(docname)
- # Suffix for the document
- source_suffix = '.' + self.env.doc2path(docname).split('.')[-1]
-
# local TOC and global TOC tree
self_toc = self.env.get_toc_for(docname, self)
toc = self.render_partial(self_toc)['fragment']
@@ -581,9 +591,8 @@ class StandaloneHTMLBuilder(Builder):
self.info(bold('copying static files... '), nonl=True)
ensuredir(path.join(self.outdir, '_static'))
# first, create pygments style file
- f = open(path.join(self.outdir, '_static', 'pygments.css'), 'w')
- f.write(self.highlighter.get_stylesheet())
- f.close()
+ with open(path.join(self.outdir, '_static', 'pygments.css'), 'w') as f:
+ f.write(self.highlighter.get_stylesheet())
# then, copy translations JavaScript file
if self.config.language is not None:
jsfile = self._get_translations_js()
@@ -605,21 +614,19 @@ class StandaloneHTMLBuilder(Builder):
# then, copy over theme-supplied static files
if self.theme:
- themeentries = [path.join(themepath, 'static')
- for themepath in self.theme.get_dirchain()[::-1]]
- for entry in themeentries:
- copy_static_entry(entry, path.join(self.outdir, '_static'),
- self, ctx)
+ for theme_path in self.theme.get_dirchain()[::-1]:
+ entry = path.join(theme_path, 'static')
+ copy_asset(entry, path.join(self.outdir, '_static'), excluded=DOTFILES,
+ context=ctx, renderer=self.templates)
# then, copy over all user-supplied static files
- staticentries = [path.join(self.confdir, spath)
- for spath in self.config.html_static_path]
- matchers = compile_matchers(self.config.exclude_patterns)
- for entry in staticentries:
+ excluded = Matcher(self.config.exclude_patterns + ["**/.*"])
+ for static_path in self.config.html_static_path:
+ entry = path.join(self.confdir, static_path)
if not path.exists(entry):
self.warn('html_static_path entry %r does not exist' % entry)
continue
- copy_static_entry(entry, path.join(self.outdir, '_static'), self,
- ctx, exclude_matchers=matchers)
+ copy_asset(entry, path.join(self.outdir, '_static'), excluded,
+ context=ctx, renderer=self.templates)
# copy logo and favicon files if not already in static path
if self.config.html_logo:
logobase = path.basename(self.config.html_logo)
@@ -642,14 +649,15 @@ class StandaloneHTMLBuilder(Builder):
def copy_extra_files(self):
# copy html_extra_path files
self.info(bold('copying extra files... '), nonl=True)
- extraentries = [path.join(self.confdir, epath)
- for epath in self.config.html_extra_path]
- matchers = compile_matchers(self.config.exclude_patterns)
- for entry in extraentries:
+ excluded = Matcher(self.config.exclude_patterns)
+
+ for extra_path in self.config.html_extra_path:
+ entry = path.join(self.confdir, extra_path)
if not path.exists(entry):
self.warn('html_extra_path entry %r does not exist' % entry)
continue
- copy_extra_entry(entry, self.outdir, matchers)
+
+ copy_asset(entry, self.outdir, excluded)
self.info('done')
def write_buildinfo(self):
@@ -712,7 +720,12 @@ class StandaloneHTMLBuilder(Builder):
def index_page(self, pagename, doctree, title):
# only index pages with title
if self.indexer is not None and title:
- self.indexer.feed(pagename, title, doctree)
+ filename = self.env.doc2path(pagename, base=None)
+ try:
+ self.indexer.feed(pagename, filename, title, doctree)
+ except TypeError:
+ # fallback for old search-adapters
+ self.indexer.feed(pagename, title, doctree)
def _get_local_toctree(self, docname, collapse=True, **kwds):
if 'includehidden' not in kwds:
@@ -1056,6 +1069,7 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
self.theme = None # no theme necessary
self.templates = None # no template bridge necessary
self.init_translator_class()
+ self.init_templates()
self.init_highlighter()
def get_target_uri(self, docname, typ=None):
@@ -1148,3 +1162,52 @@ class JSONHTMLBuilder(SerializingHTMLBuilder):
def init(self):
SerializingHTMLBuilder.init(self)
+
+
+def setup(app):
+ # builders
+ app.add_builder(StandaloneHTMLBuilder)
+ app.add_builder(DirectoryHTMLBuilder)
+ app.add_builder(SingleFileHTMLBuilder)
+ app.add_builder(PickleHTMLBuilder)
+ app.add_builder(JSONHTMLBuilder)
+
+ # config values
+ app.add_config_value('html_theme', 'alabaster', 'html')
+ app.add_config_value('html_theme_path', [], 'html')
+ app.add_config_value('html_theme_options', {}, 'html')
+ app.add_config_value('html_title',
+ lambda self: l_('%s %s documentation') % (self.project, self.release),
+ 'html', string_classes)
+ app.add_config_value('html_short_title', lambda self: self.html_title, 'html')
+ app.add_config_value('html_style', None, 'html', string_classes)
+ app.add_config_value('html_logo', None, 'html', string_classes)
+ app.add_config_value('html_favicon', None, 'html', string_classes)
+ app.add_config_value('html_static_path', [], 'html')
+ app.add_config_value('html_extra_path', [], 'html')
+ app.add_config_value('html_last_updated_fmt', None, 'html', string_classes)
+ app.add_config_value('html_use_smartypants', True, 'html')
+ app.add_config_value('html_translator_class', None, 'html', string_classes)
+ app.add_config_value('html_sidebars', {}, 'html')
+ app.add_config_value('html_additional_pages', {}, 'html')
+ app.add_config_value('html_use_modindex', True, 'html') # deprecated
+ app.add_config_value('html_domain_indices', True, 'html', [list])
+ app.add_config_value('html_add_permalinks', u'\u00B6', 'html')
+ app.add_config_value('html_use_index', True, 'html')
+ app.add_config_value('html_split_index', False, 'html')
+ app.add_config_value('html_copy_source', True, 'html')
+ app.add_config_value('html_show_sourcelink', True, 'html')
+ app.add_config_value('html_sourcelink_suffix', '.txt', 'html')
+ app.add_config_value('html_use_opensearch', '', 'html')
+ app.add_config_value('html_file_suffix', None, 'html', string_classes)
+ app.add_config_value('html_link_suffix', None, 'html', string_classes)
+ app.add_config_value('html_show_copyright', True, 'html')
+ app.add_config_value('html_show_sphinx', True, 'html')
+ app.add_config_value('html_context', {}, 'html')
+ app.add_config_value('html_output_encoding', 'utf-8', 'html')
+ app.add_config_value('html_compact_lists', True, 'html')
+ app.add_config_value('html_secnumber_suffix', '. ', 'html')
+ app.add_config_value('html_search_language', None, 'html', string_classes)
+ app.add_config_value('html_search_options', {}, 'html')
+ app.add_config_value('html_search_scorer', '', None)
+ app.add_config_value('html_scaled_image_link', True, 'html')
diff --git a/sphinx/builders/htmlhelp.py b/sphinx/builders/htmlhelp.py
index b1a5d7dda..cdb51b2c6 100644
--- a/sphinx/builders/htmlhelp.py
+++ b/sphinx/builders/htmlhelp.py
@@ -18,6 +18,7 @@ from os import path
from docutils import nodes
from sphinx import addnodes
+from sphinx.util.osutil import make_filename
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.util.pycompat import htmlescape
@@ -63,7 +64,7 @@ Binary Index=No
Compiled file=%(outname)s.chm
Contents file=%(outname)s.hhc
Default Window=%(outname)s
-Default topic=index.html
+Default topic=%(master_doc)s
Display compile progress=No
Full text search stop list file=%(outname)s.stp
Full-text search=Yes
@@ -73,7 +74,7 @@ Title=%(title)s
[WINDOWS]
%(outname)s="%(title)s","%(outname)s.hhc","%(outname)s.hhk",\
-"index.html","index.html",,,,,0x63520,220,0x10384e,[0,0,1024,768],,,,,,,0
+"%(master_doc)s","%(master_doc)s",,,,,0x63520,220,0x10384e,[0,0,1024,768],,,,,,,0
[FILES]
'''
@@ -183,6 +184,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
StandaloneHTMLBuilder.init(self)
# the output files for HTML help must be .html only
self.out_suffix = '.html'
+ self.link_suffix = '.html'
# determine the correct locale setting
locale = chm_locales.get(self.config.language)
if locale is not None:
@@ -204,11 +206,14 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
self.info('writing project file...')
with self.open_file(outdir, outname+'.hhp') as f:
- f.write(project_template % {'outname': outname,
- 'title': self.config.html_title,
- 'version': self.config.version,
- 'project': self.config.project,
- 'lcid': self.lcid})
+ f.write(project_template % {
+ 'outname': outname,
+ 'title': self.config.html_title,
+ 'version': self.config.version,
+ 'project': self.config.project,
+ 'lcid': self.lcid,
+ 'master_doc': self.config.master_doc + self.out_suffix
+ })
if not outdir.endswith(os.sep):
outdir += os.sep
olen = len(outdir)
@@ -225,7 +230,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
f.write(contents_header)
# special books
f.write('<LI> ' + object_sitemap % (self.config.html_short_title,
- 'index.html'))
+ self.config.master_doc + self.out_suffix))
for indexname, indexcls, content, collapse in self.domain_indices:
f.write('<LI> ' + object_sitemap % (indexcls.localname,
'%s.html' % indexname))
@@ -292,3 +297,10 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
for title, (refs, subitems, key_) in group:
write_index(title, refs, subitems)
f.write('</UL>\n')
+
+
+def setup(app):
+ app.setup_extension('sphinx.builders.html')
+ app.add_builder(HTMLHelpBuilder)
+
+ app.add_config_value('htmlhelp_basename', lambda self: make_filename(self.project), None)
diff --git a/sphinx/builders/latex.py b/sphinx/builders/latex.py
index ac26e33c9..51d361d5e 100644
--- a/sphinx/builders/latex.py
+++ b/sphinx/builders/latex.py
@@ -11,7 +11,6 @@
import os
from os import path
-import warnings
from six import iteritems
from docutils import nodes
@@ -19,14 +18,16 @@ from docutils.io import FileOutput
from docutils.utils import new_document
from docutils.frontend import OptionParser
-from sphinx import package_dir, addnodes
+from sphinx import package_dir, addnodes, highlighting
from sphinx.util import texescape
+from sphinx.config import string_classes, ENUM
from sphinx.errors import SphinxError
from sphinx.locale import _
from sphinx.builders import Builder
from sphinx.environment import NoUri
from sphinx.util.nodes import inline_all_toctrees
-from sphinx.util.osutil import SEP, copyfile
+from sphinx.util.fileutil import copy_asset_file
+from sphinx.util.osutil import SEP, make_filename
from sphinx.util.console import bold, darkgreen
from sphinx.writers.latex import LaTeXWriter
@@ -38,27 +39,12 @@ class LaTeXBuilder(Builder):
name = 'latex'
format = 'latex'
supported_image_types = ['application/pdf', 'image/png', 'image/jpeg']
- usepackages = []
def init(self):
self.docnames = []
self.document_data = []
+ self.usepackages = []
texescape.init()
- self.check_options()
-
- def check_options(self):
- if self.config.latex_toplevel_sectioning not in (None, 'part', 'chapter', 'section'):
- self.warn('invalid latex_toplevel_sectioning, ignored: %s' %
- self.config.latex_top_sectionlevel)
- self.config.latex_top_sectionlevel = None
-
- if self.config.latex_use_parts:
- warnings.warn('latex_use_parts will be removed at Sphinx-1.5. '
- 'Use latex_toplevel_sectioning instead.',
- DeprecationWarning)
-
- if self.config.latex_toplevel_sectioning:
- self.warn('latex_use_parts conflicts with latex_toplevel_sectioning, ignored.')
def get_outdated_docs(self):
return 'all documents' # for now
@@ -92,6 +78,16 @@ class LaTeXBuilder(Builder):
docname = docname[:-5]
self.titles.append((docname, entry[2]))
+ def write_stylesheet(self):
+ highlighter = highlighting.PygmentsBridge(
+ 'latex', self.config.pygments_style, self.config.trim_doctest_flags)
+ stylesheet = path.join(self.outdir, 'sphinxhighlight.sty')
+ with open(stylesheet, 'w') as f:
+ f.write('\\NeedsTeXFormat{LaTeX2e}[1995/12/01]\n')
+ f.write('\\ProvidesPackage{sphinxhighlight}'
+ '[2016/05/29 stylesheet for highlighting with pygments]\n\n')
+ f.write(highlighter.get_stylesheet())
+
def write(self, *ignored):
docwriter = LaTeXWriter(self)
docsettings = OptionParser(
@@ -100,6 +96,7 @@ class LaTeXBuilder(Builder):
read_config_files=True).get_default_values()
self.init_document_data()
+ self.write_stylesheet()
for entry in self.document_data:
docname, targetname, title, author, docclass = entry[:5]
@@ -192,33 +189,109 @@ class LaTeXBuilder(Builder):
self.info(bold('copying images...'), nonl=1)
for src, dest in iteritems(self.images):
self.info(' '+src, nonl=1)
- copyfile(path.join(self.srcdir, src),
- path.join(self.outdir, dest))
+ copy_asset_file(path.join(self.srcdir, src),
+ path.join(self.outdir, dest))
self.info()
# copy TeX support files from texinputs
+ context = {'latex_engine': self.config.latex_engine}
self.info(bold('copying TeX support files...'))
staticdirname = path.join(package_dir, 'texinputs')
for filename in os.listdir(staticdirname):
if not filename.startswith('.'):
- copyfile(path.join(staticdirname, filename),
- path.join(self.outdir, filename))
+ copy_asset_file(path.join(staticdirname, filename),
+ self.outdir, context=context)
# copy additional files
if self.config.latex_additional_files:
self.info(bold('copying additional files...'), nonl=1)
for filename in self.config.latex_additional_files:
self.info(' '+filename, nonl=1)
- copyfile(path.join(self.confdir, filename),
- path.join(self.outdir, path.basename(filename)))
+ copy_asset_file(path.join(self.confdir, filename), self.outdir)
self.info()
# the logo is handled differently
if self.config.latex_logo:
- logobase = path.basename(self.config.latex_logo)
- logotarget = path.join(self.outdir, logobase)
if not path.isfile(path.join(self.confdir, self.config.latex_logo)):
raise SphinxError('logo file %r does not exist' % self.config.latex_logo)
- elif not path.isfile(logotarget):
- copyfile(path.join(self.confdir, self.config.latex_logo), logotarget)
+ else:
+ copy_asset_file(path.join(self.confdir, self.config.latex_logo), self.outdir)
self.info('done')
+
+
+def validate_config_values(app):
+ if app.config.latex_toplevel_sectioning not in (None, 'part', 'chapter', 'section'):
+ app.warn('invalid latex_toplevel_sectioning, ignored: %s' %
+ app.config.latex_toplevel_sectioning)
+ app.config.latex_toplevel_sectioning = None
+
+ if app.config.latex_use_parts:
+ if app.config.latex_toplevel_sectioning:
+ app.warn('latex_use_parts conflicts with latex_toplevel_sectioning, ignored.')
+ else:
+ app.warn('latex_use_parts is deprecated. Use latex_toplevel_sectioning instead.')
+ app.config.latex_toplevel_sectioning = 'parts'
+
+ if app.config.latex_use_modindex is not True: # changed by user
+ app.warn('latex_use_modeindex is deprecated. Use latex_domain_indices instead.')
+
+ if app.config.latex_preamble:
+ if app.config.latex_elements.get('preamble'):
+ app.warn("latex_preamble conflicts with latex_elements['preamble'], ignored.")
+ else:
+ app.warn("latex_preamble is deprecated. Use latex_elements['preamble'] instead.")
+ app.config.latex_elements['preamble'] = app.config.latex_preamble
+
+ if app.config.latex_paper_size != 'letter':
+ if app.config.latex_elements.get('papersize'):
+ app.warn("latex_paper_size conflicts with latex_elements['papersize'], ignored.")
+ else:
+ app.warn("latex_paper_size is deprecated. "
+ "Use latex_elements['papersize'] instead.")
+ if app.config.latex_paper_size:
+ app.config.latex_elements['papersize'] = app.config.latex_paper_size + 'paper'
+
+ if app.config.latex_font_size != '10pt':
+ if app.config.latex_elements.get('pointsize'):
+ app.warn("latex_font_size conflicts with latex_elements['pointsize'], ignored.")
+ else:
+ app.warn("latex_font_size is deprecated. Use latex_elements['pointsize'] instead.")
+ app.config.latex_elements['pointsize'] = app.config.latex_font_size
+
+
+def setup(app):
+ app.add_builder(LaTeXBuilder)
+ app.connect('builder-inited', validate_config_values)
+
+ app.add_config_value('latex_engine',
+ lambda self: 'pdflatex' if self.language != 'ja' else 'platex',
+ None,
+ ENUM('pdflatex', 'xelatex', 'lualatex', 'platex'))
+ app.add_config_value('latex_documents',
+ lambda self: [(self.master_doc, make_filename(self.project) + '.tex',
+ self.project, '', 'manual')],
+ None)
+ app.add_config_value('latex_logo', None, None, string_classes)
+ app.add_config_value('latex_appendices', [], None)
+ app.add_config_value('latex_keep_old_macro_names', True, None)
+ # now deprecated - use latex_toplevel_sectioning
+ app.add_config_value('latex_use_parts', False, None)
+ app.add_config_value('latex_toplevel_sectioning', None, None, [str])
+ app.add_config_value('latex_use_modindex', True, None) # deprecated
+ app.add_config_value('latex_domain_indices', True, None, [list])
+ app.add_config_value('latex_show_urls', 'no', None)
+ app.add_config_value('latex_show_pagerefs', False, None)
+ # paper_size and font_size are still separate values
+ # so that you can give them easily on the command line
+ app.add_config_value('latex_paper_size', 'letter', None)
+ app.add_config_value('latex_font_size', '10pt', None)
+ app.add_config_value('latex_elements', {}, None)
+ app.add_config_value('latex_additional_files', [], None)
+
+ japanese_default = {'manual': 'jsbook',
+ 'howto': 'jreport'}
+ app.add_config_value('latex_docclass',
+ lambda self: japanese_default if self.language == 'ja' else {},
+ None)
+ # now deprecated - use latex_elements
+ app.add_config_value('latex_preamble', '', None)
diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py
index 7c30597a8..dfaeb5bba 100644
--- a/sphinx/builders/linkcheck.py
+++ b/sphinx/builders/linkcheck.py
@@ -54,6 +54,13 @@ except pkg_resources.DistributionNotFound:
'install "requests[security]" as a dependency or upgrade to '
'a python version with SNI support (Python 3 and Python 2.7.9+).'
)
+except pkg_resources.UnknownExtra:
+ warnings.warn(
+ 'Some links may return broken results due to being unable to '
+ 'check the Server Name Indication (SNI) in the returned SSL cert '
+ 'against the hostname in the url requested. Recommended to '
+ 'install requests-2.4.1+.'
+ )
requests_user_agent = [('User-agent', 'Mozilla/5.0 (X11; Linux x86_64; rv:25.0) '
'Gecko/20100101 Firefox/25.0')]
@@ -300,3 +307,13 @@ class CheckExternalLinksBuilder(Builder):
def finish(self):
for worker in self.workers:
self.wqueue.put((None, None, None), False)
+
+
+def setup(app):
+ app.add_builder(CheckExternalLinksBuilder)
+
+ app.add_config_value('linkcheck_ignore', [], None)
+ app.add_config_value('linkcheck_retries', 1, None)
+ app.add_config_value('linkcheck_timeout', None, None, [int])
+ app.add_config_value('linkcheck_workers', 5, None)
+ app.add_config_value('linkcheck_anchors', True, None)
diff --git a/sphinx/builders/manpage.py b/sphinx/builders/manpage.py
index a2e75f9f7..248ed40b2 100644
--- a/sphinx/builders/manpage.py
+++ b/sphinx/builders/manpage.py
@@ -19,6 +19,7 @@ from sphinx import addnodes
from sphinx.builders import Builder
from sphinx.environment import NoUri
from sphinx.util.nodes import inline_all_toctrees
+from sphinx.util.osutil import make_filename
from sphinx.util.console import bold, darkgreen
from sphinx.writers.manpage import ManualPageWriter
@@ -88,3 +89,13 @@ class ManualPageBuilder(Builder):
def finish(self):
pass
+
+
+def setup(app):
+ app.add_builder(ManualPageBuilder)
+
+ app.add_config_value('man_pages',
+ lambda self: [(self.master_doc, make_filename(self.project).lower(),
+ '%s %s' % (self.project, self.release), [], 1)],
+ None)
+ app.add_config_value('man_show_urls', False, None)
diff --git a/sphinx/builders/qthelp.py b/sphinx/builders/qthelp.py
index 4139c92c6..c53b56657 100644
--- a/sphinx/builders/qthelp.py
+++ b/sphinx/builders/qthelp.py
@@ -21,6 +21,7 @@ from docutils import nodes
from sphinx import addnodes
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.util import force_decode
+from sphinx.util.osutil import make_filename
from sphinx.util.pycompat import htmlescape
@@ -104,15 +105,25 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
# don't add links
add_permalinks = False
+
# don't add sidebar etc.
embedded = True
+ # disable download role
+ download_support = False
+
+ # don't generate the search index or include the search page
+ search = False
def init(self):
StandaloneHTMLBuilder.init(self)
# the output files for HTML help must be .html only
self.out_suffix = '.html'
+ self.link_suffix = '.html'
# self.config.html_style = 'traditional.css'
+ def get_theme_config(self):
+ return self.config.qthelp_theme, self.config.qthelp_theme_options
+
def handle_finish(self):
self.build_qhp(self.outdir, self.config.qthelp_basename)
@@ -290,3 +301,12 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
keywords.extend(self.build_keywords(subitem[0], subitem[1], []))
return keywords
+
+
+def setup(app):
+ app.setup_extension('sphinx.builders.html')
+ app.add_builder(QtHelpBuilder)
+
+ app.add_config_value('qthelp_basename', lambda self: make_filename(self.project), None)
+ app.add_config_value('qthelp_theme', 'nonav', 'html')
+ app.add_config_value('qthelp_theme_options', {}, 'html')
diff --git a/sphinx/builders/texinfo.py b/sphinx/builders/texinfo.py
index 8c4bd2419..f070840b6 100644
--- a/sphinx/builders/texinfo.py
+++ b/sphinx/builders/texinfo.py
@@ -22,7 +22,7 @@ from sphinx.locale import _
from sphinx.builders import Builder
from sphinx.environment import NoUri
from sphinx.util.nodes import inline_all_toctrees
-from sphinx.util.osutil import SEP, copyfile
+from sphinx.util.osutil import SEP, copyfile, make_filename
from sphinx.util.console import bold, darkgreen
from sphinx.writers.texinfo import TexinfoWriter
@@ -225,3 +225,20 @@ class TexinfoBuilder(Builder):
except (IOError, OSError) as err:
self.warn("error writing file %s: %s" % (fn, err))
self.info(' done')
+
+
+def setup(app):
+ app.add_builder(TexinfoBuilder)
+
+ app.add_config_value('texinfo_documents',
+ lambda self: [(self.master_doc, make_filename(self.project).lower(),
+ self.project, '', make_filename(self.project),
+ 'The %s reference manual.' %
+ make_filename(self.project),
+ 'Python')],
+ None)
+ app.add_config_value('texinfo_appendices', [], None)
+ app.add_config_value('texinfo_elements', {}, None)
+ app.add_config_value('texinfo_domain_indices', True, None, [list])
+ app.add_config_value('texinfo_show_urls', 'footnote', None)
+ app.add_config_value('texinfo_no_detailmenu', False, None)
diff --git a/sphinx/builders/text.py b/sphinx/builders/text.py
index 202ec20db..2daf8b043 100644
--- a/sphinx/builders/text.py
+++ b/sphinx/builders/text.py
@@ -67,3 +67,10 @@ class TextBuilder(Builder):
def finish(self):
pass
+
+
+def setup(app):
+ app.add_builder(TextBuilder)
+
+ app.add_config_value('text_sectionchars', '*=-~"+`', 'env')
+ app.add_config_value('text_newlines', 'unix', 'env')
diff --git a/sphinx/builders/websupport.py b/sphinx/builders/websupport.py
index 843b0899e..d8ff5ad8d 100644
--- a/sphinx/builders/websupport.py
+++ b/sphinx/builders/websupport.py
@@ -165,3 +165,7 @@ class WebSupportBuilder(PickleHTMLBuilder):
def dump_search_index(self):
self.indexer.finish_indexing()
+
+
+def setup(app):
+ app.add_builder(WebSupportBuilder)
diff --git a/sphinx/builders/xml.py b/sphinx/builders/xml.py
index 589e8a63a..e0e33312c 100644
--- a/sphinx/builders/xml.py
+++ b/sphinx/builders/xml.py
@@ -95,3 +95,10 @@ class PseudoXMLBuilder(XMLBuilder):
out_suffix = '.pseudoxml'
_writer_class = PseudoXMLWriter
+
+
+def setup(app):
+ app.add_builder(XMLBuilder)
+ app.add_builder(PseudoXMLBuilder)
+
+ app.add_config_value('xml_pretty', True, 'env')
diff --git a/sphinx/config.py b/sphinx/config.py
index ef57334fe..9de59a9ff 100644
--- a/sphinx/config.py
+++ b/sphinx/config.py
@@ -10,14 +10,13 @@
"""
import re
-from os import path, environ, getenv
-import shlex
+from os import path, getenv
from six import PY2, PY3, iteritems, string_types, binary_type, text_type, integer_types
from sphinx.errors import ConfigError
from sphinx.locale import l_
-from sphinx.util.osutil import make_filename, cd
+from sphinx.util.osutil import cd
from sphinx.util.pycompat import execfile_, NoneType
from sphinx.util.i18n import format_date
@@ -29,10 +28,25 @@ if PY3:
CONFIG_SYNTAX_ERROR += "\nDid you change the syntax from 2.x to 3.x?"
CONFIG_EXIT_ERROR = "The configuration file (or one of the modules it imports) " \
"called sys.exit()"
+CONFIG_ENUM_WARNING = "The config value `{name}` has to be a one of {candidates}, " \
+ "but `{current}` is given."
CONFIG_TYPE_WARNING = "The config value `{name}' has type `{current.__name__}', " \
"defaults to `{default.__name__}.'"
+class ENUM:
+ """represents the config value should be a one of candidates.
+
+ Example:
+ app.add_config_value('latex_show_urls', 'no', ENUM('no', 'footnote', 'inline'))
+ """
+ def __init__(self, *candidates):
+ self.candidates = candidates
+
+ def match(self, value):
+ return value in self.candidates
+
+
string_classes = [text_type]
if PY2:
string_classes.append(binary_type) # => [str, unicode]
@@ -94,192 +108,12 @@ class Config(object):
'table': l_('Table %s'),
'code-block': l_('Listing %s')},
'env'),
-
- # HTML options
- html_theme = ('alabaster', 'html'),
- html_theme_path = ([], 'html'),
- html_theme_options = ({}, 'html'),
- html_title = (lambda self: l_('%s %s documentation') %
- (self.project, self.release),
- 'html', string_classes),
- html_short_title = (lambda self: self.html_title, 'html'),
- html_style = (None, 'html', string_classes),
- html_logo = (None, 'html', string_classes),
- html_favicon = (None, 'html', string_classes),
- html_static_path = ([], 'html'),
- html_extra_path = ([], 'html'),
- # the real default is locale-dependent
- html_last_updated_fmt = (None, 'html', string_classes),
- html_use_smartypants = (True, 'html'),
- html_translator_class = (None, 'html', string_classes),
- html_sidebars = ({}, 'html'),
- html_additional_pages = ({}, 'html'),
- html_use_modindex = (True, 'html'), # deprecated
- html_domain_indices = (True, 'html', [list]),
- html_add_permalinks = (u'\u00B6', 'html'),
- html_use_index = (True, 'html'),
- html_split_index = (False, 'html'),
- html_copy_source = (True, 'html'),
- html_show_sourcelink = (True, 'html'),
- html_use_opensearch = ('', 'html'),
- html_file_suffix = (None, 'html', string_classes),
- html_link_suffix = (None, 'html', string_classes),
- html_show_copyright = (True, 'html'),
- html_show_sphinx = (True, 'html'),
- html_context = ({}, 'html'),
- html_output_encoding = ('utf-8', 'html'),
- html_compact_lists = (True, 'html'),
- html_secnumber_suffix = ('. ', 'html'),
- html_search_language = (None, 'html', string_classes),
- html_search_options = ({}, 'html'),
- html_search_scorer = ('', None),
- html_scaled_image_link = (True, 'html'),
-
- # HTML help only options
- htmlhelp_basename = (lambda self: make_filename(self.project), None),
-
- # Qt help only options
- qthelp_basename = (lambda self: make_filename(self.project), None),
-
- # Devhelp only options
- devhelp_basename = (lambda self: make_filename(self.project), None),
-
- # Apple help options
- applehelp_bundle_name = (lambda self: make_filename(self.project),
- 'applehelp'),
- applehelp_bundle_id = (None, 'applehelp', string_classes),
- applehelp_dev_region = ('en-us', 'applehelp'),
- applehelp_bundle_version = ('1', 'applehelp'),
- applehelp_icon = (None, 'applehelp', string_classes),
- applehelp_kb_product = (lambda self: '%s-%s' %
- (make_filename(self.project), self.release),
- 'applehelp'),
- applehelp_kb_url = (None, 'applehelp', string_classes),
- applehelp_remote_url = (None, 'applehelp', string_classes),
- applehelp_index_anchors = (False, 'applehelp', string_classes),
- applehelp_min_term_length = (None, 'applehelp', string_classes),
- applehelp_stopwords = (lambda self: self.language or 'en', 'applehelp'),
- applehelp_locale = (lambda self: self.language or 'en', 'applehelp'),
- applehelp_title = (lambda self: self.project + ' Help', 'applehelp'),
- applehelp_codesign_identity = (lambda self:
- environ.get('CODE_SIGN_IDENTITY', None),
- 'applehelp'),
- applehelp_codesign_flags = (lambda self:
- shlex.split(
- environ.get('OTHER_CODE_SIGN_FLAGS',
- '')),
- 'applehelp'),
- applehelp_indexer_path = ('/usr/bin/hiutil', 'applehelp'),
- applehelp_codesign_path = ('/usr/bin/codesign', 'applehelp'),
- applehelp_disable_external_tools = (False, None),
-
- # Epub options
- epub_basename = (lambda self: make_filename(self.project), None),
- epub_theme = ('epub', 'html'),
- epub_theme_options = ({}, 'html'),
- epub_title = (lambda self: self.html_title, 'html'),
- epub3_description = ('', 'epub3', string_classes),
- epub_author = ('unknown', 'html'),
- epub3_contributor = ('unknown', 'epub3', string_classes),
- epub_language = (lambda self: self.language or 'en', 'html'),
- epub_publisher = ('unknown', 'html'),
- epub_copyright = (lambda self: self.copyright, 'html'),
- epub_identifier = ('unknown', 'html'),
- epub_scheme = ('unknown', 'html'),
- epub_uid = ('unknown', 'env'),
- epub_cover = ((), 'env'),
- epub_guide = ((), 'env'),
- epub_pre_files = ([], 'env'),
- epub_post_files = ([], 'env'),
- epub_exclude_files = ([], 'env'),
- epub_tocdepth = (3, 'env'),
- epub_tocdup = (True, 'env'),
- epub_tocscope = ('default', 'env'),
- epub_fix_images = (False, 'env'),
- epub_max_image_width = (0, 'env'),
- epub_show_urls = ('inline', 'html'),
- epub_use_index = (lambda self: self.html_use_index, 'html'),
- epub3_page_progression_direction = ('ltr', 'epub3', string_classes),
-
- # LaTeX options
- latex_documents = (lambda self: [(self.master_doc,
- make_filename(self.project) + '.tex',
- self.project,
- '', 'manual')],
- None),
- latex_logo = (None, None, string_classes),
- latex_appendices = ([], None),
- # now deprecated - use latex_toplevel_sectioning
- latex_use_parts = (False, None),
- latex_toplevel_sectioning = (None, None, [str]),
- latex_use_modindex = (True, None), # deprecated
- latex_domain_indices = (True, None, [list]),
- latex_show_urls = ('no', None),
- latex_show_pagerefs = (False, None),
- # paper_size and font_size are still separate values
- # so that you can give them easily on the command line
- latex_paper_size = ('letter', None),
- latex_font_size = ('10pt', None),
- latex_elements = ({}, None),
- latex_additional_files = ([], None),
- latex_docclass = ({}, None),
- # now deprecated - use latex_elements
- latex_preamble = ('', None),
-
- # text options
- text_sectionchars = ('*=-~"+`', 'env'),
- text_newlines = ('unix', 'env'),
-
- # manpage options
- man_pages = (lambda self: [(self.master_doc,
- make_filename(self.project).lower(),
- '%s %s' % (self.project, self.release),
- [], 1)],
- None),
- man_show_urls = (False, None),
-
- # Texinfo options
- texinfo_documents = (lambda self: [(self.master_doc,
- make_filename(self.project).lower(),
- self.project, '',
- make_filename(self.project),
- 'The %s reference manual.' %
- make_filename(self.project),
- 'Python')],
- None),
- texinfo_appendices = ([], None),
- texinfo_elements = ({}, None),
- texinfo_domain_indices = (True, None, [list]),
- texinfo_show_urls = ('footnote', None),
- texinfo_no_detailmenu = (False, None),
-
- # linkcheck options
- linkcheck_ignore = ([], None),
- linkcheck_retries = (1, None),
- linkcheck_timeout = (None, None, [int]),
- linkcheck_workers = (5, None),
- linkcheck_anchors = (True, None),
-
- # gettext options
- gettext_compact = (True, 'gettext'),
- gettext_location = (True, 'gettext'),
- gettext_uuid = (False, 'gettext'),
- gettext_auto_build = (True, 'env'),
- gettext_additional_targets = ([], 'env'),
-
- # XML options
- xml_pretty = (True, 'env'),
)
def __init__(self, dirname, filename, overrides, tags):
self.overrides = overrides
self.values = Config.config_values.copy()
config = {}
- if 'extensions' in overrides: # XXX do we need this?
- if isinstance(overrides['extensions'], string_types):
- config['extensions'] = overrides.pop('extensions').split(',')
- else:
- config['extensions'] = overrides.pop('extensions')
if dirname is not None:
config_file = path.join(dirname, filename)
config['__file__'] = config_file
@@ -298,6 +132,12 @@ class Config(object):
# these two must be preinitialized because extensions can add their
# own config values
self.setup = config.get('setup', None)
+
+ if 'extensions' in overrides:
+ if isinstance(overrides['extensions'], string_types):
+ config['extensions'] = overrides.pop('extensions').split(',')
+ else:
+ config['extensions'] = overrides.pop('extensions')
self.extensions = config.get('extensions', [])
# correct values of copyright year that are not coherent with
@@ -326,19 +166,24 @@ class Config(object):
if default is None and not permitted:
continue # neither inferrable nor expliclitly permitted types
current = self[name]
- if type(current) is type(default):
- continue
- if type(current) in permitted:
- continue
-
- common_bases = (set(type(current).__bases__ + (type(current),)) &
- set(type(default).__bases__))
- common_bases.discard(object)
- if common_bases:
- continue # at least we share a non-trivial base class
-
- warn(CONFIG_TYPE_WARNING.format(
- name=name, current=type(current), default=type(default)))
+ if isinstance(permitted, ENUM):
+ if not permitted.match(current):
+ warn(CONFIG_ENUM_WARNING.format(
+ name=name, current=current, candidates=permitted.candidates))
+ else:
+ if type(current) is type(default):
+ continue
+ if type(current) in permitted:
+ continue
+
+ common_bases = (set(type(current).__bases__ + (type(current),)) &
+ set(type(default).__bases__))
+ common_bases.discard(object)
+ if common_bases:
+ continue # at least we share a non-trivial base class
+
+ warn(CONFIG_TYPE_WARNING.format(
+ name=name, current=type(current), default=type(default)))
def check_unicode(self, warn):
# check all string values for non-ASCII characters in bytestrings,
diff --git a/sphinx/directives/__init__.py b/sphinx/directives/__init__.py
index d99a9bc1b..b0c69a8e1 100644
--- a/sphinx/directives/__init__.py
+++ b/sphinx/directives/__init__.py
@@ -17,11 +17,6 @@ from docutils.parsers.rst import Directive, directives, roles
from sphinx import addnodes
from sphinx.util.docfields import DocFieldTransformer
-# import and register directives
-from sphinx.directives.code import * # noqa
-from sphinx.directives.other import * # noqa
-from sphinx.directives.patches import * # noqa
-
# RE to strip backslash escapes
nl_escape_re = re.compile(r'\\\n')
@@ -216,8 +211,9 @@ class DefaultDomain(Directive):
return []
-directives.register_directive('default-role', DefaultRole)
-directives.register_directive('default-domain', DefaultDomain)
-directives.register_directive('describe', ObjectDescription)
-# new, more consistent, name
-directives.register_directive('object', ObjectDescription)
+def setup(app):
+ directives.register_directive('default-role', DefaultRole)
+ directives.register_directive('default-domain', DefaultDomain)
+ directives.register_directive('describe', ObjectDescription)
+ # new, more consistent, name
+ directives.register_directive('object', ObjectDescription)
diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py
index de804f988..f88b30987 100644
--- a/sphinx/directives/code.py
+++ b/sphinx/directives/code.py
@@ -342,8 +342,9 @@ class LiteralInclude(Directive):
return [retnode]
-directives.register_directive('highlight', Highlight)
-directives.register_directive('highlightlang', Highlight) # old
-directives.register_directive('code-block', CodeBlock)
-directives.register_directive('sourcecode', CodeBlock)
-directives.register_directive('literalinclude', LiteralInclude)
+def setup(app):
+ directives.register_directive('highlight', Highlight)
+ directives.register_directive('highlightlang', Highlight) # old
+ directives.register_directive('code-block', CodeBlock)
+ directives.register_directive('sourcecode', CodeBlock)
+ directives.register_directive('literalinclude', LiteralInclude)
diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py
index 51294570c..a24a40a49 100644
--- a/sphinx/directives/other.py
+++ b/sphinx/directives/other.py
@@ -405,27 +405,29 @@ class Include(BaseInclude):
return BaseInclude.run(self)
rel_filename, filename = env.relfn2path(self.arguments[0])
self.arguments[0] = filename
+ env.note_included(filename)
return BaseInclude.run(self)
-directives.register_directive('toctree', TocTree)
-directives.register_directive('sectionauthor', Author)
-directives.register_directive('moduleauthor', Author)
-directives.register_directive('codeauthor', Author)
-directives.register_directive('index', Index)
-directives.register_directive('deprecated', VersionChange)
-directives.register_directive('versionadded', VersionChange)
-directives.register_directive('versionchanged', VersionChange)
-directives.register_directive('seealso', SeeAlso)
-directives.register_directive('tabularcolumns', TabularColumns)
-directives.register_directive('centered', Centered)
-directives.register_directive('acks', Acks)
-directives.register_directive('hlist', HList)
-directives.register_directive('only', Only)
-directives.register_directive('include', Include)
-
-# register the standard rst class directive under a different name
-# only for backwards compatibility now
-directives.register_directive('cssclass', Class)
-# new standard name when default-domain with "class" is in effect
-directives.register_directive('rst-class', Class)
+def setup(app):
+ directives.register_directive('toctree', TocTree)
+ directives.register_directive('sectionauthor', Author)
+ directives.register_directive('moduleauthor', Author)
+ directives.register_directive('codeauthor', Author)
+ directives.register_directive('index', Index)
+ directives.register_directive('deprecated', VersionChange)
+ directives.register_directive('versionadded', VersionChange)
+ directives.register_directive('versionchanged', VersionChange)
+ directives.register_directive('seealso', SeeAlso)
+ directives.register_directive('tabularcolumns', TabularColumns)
+ directives.register_directive('centered', Centered)
+ directives.register_directive('acks', Acks)
+ directives.register_directive('hlist', HList)
+ directives.register_directive('only', Only)
+ directives.register_directive('include', Include)
+
+ # register the standard rst class directive under a different name
+ # only for backwards compatibility now
+ directives.register_directive('cssclass', Class)
+ # new standard name when default-domain with "class" is in effect
+ directives.register_directive('rst-class', Class)
diff --git a/sphinx/directives/patches.py b/sphinx/directives/patches.py
index 4f6f3729f..a4a046917 100644
--- a/sphinx/directives/patches.py
+++ b/sphinx/directives/patches.py
@@ -35,4 +35,5 @@ class Figure(images.Figure):
return [figure_node]
-directives.register_directive('figure', Figure)
+def setup(app):
+ directives.register_directive('figure', Figure)
diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py
index e4d397efe..c67abc207 100644
--- a/sphinx/domains/__init__.py
+++ b/sphinx/domains/__init__.py
@@ -273,20 +273,3 @@ class Domain(object):
if primary:
return type.lname
return _('%s %s') % (self.label, type.lname)
-
-
-from sphinx.domains.c import CDomain # noqa
-from sphinx.domains.cpp import CPPDomain # noqa
-from sphinx.domains.std import StandardDomain # noqa
-from sphinx.domains.python import PythonDomain # noqa
-from sphinx.domains.javascript import JavaScriptDomain # noqa
-from sphinx.domains.rst import ReSTDomain # noqa
-
-BUILTIN_DOMAINS = {
- 'std': StandardDomain,
- 'py': PythonDomain,
- 'c': CDomain,
- 'cpp': CPPDomain,
- 'js': JavaScriptDomain,
- 'rst': ReSTDomain,
-}
diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py
index c7fd0681e..43e869dbc 100644
--- a/sphinx/domains/c.py
+++ b/sphinx/domains/c.py
@@ -279,6 +279,9 @@ class CDomain(Domain):
typ, target, node, contnode):
# strip pointer asterisk
target = target.rstrip(' *')
+ # becase TypedField can generate xrefs
+ if target in CObject.stopwords:
+ return contnode
if target not in self.data['objects']:
return None
obj = self.data['objects'][target]
@@ -299,3 +302,7 @@ class CDomain(Domain):
def get_objects(self):
for refname, (docname, type) in list(self.data['objects'].items()):
yield (refname, refname, type, docname, 'c.' + refname, 1)
+
+
+def setup(app):
+ app.add_domain(CDomain)
diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py
index d53b9431d..2b6958768 100644
--- a/sphinx/domains/cpp.py
+++ b/sphinx/domains/cpp.py
@@ -553,6 +553,80 @@ def _verify_description_mode(mode):
raise Exception("Description mode '%s' is invalid." % mode)
+class ASTCPPAttribute(ASTBase):
+ def __init__(self, arg):
+ self.arg = arg
+
+ def __unicode__(self):
+ return "[[" + self.arg + "]]"
+
+ def describe_signature(self, signode):
+ txt = text_type(self)
+ signode.append(nodes.Text(txt, txt))
+
+
+class ASTGnuAttribute(ASTBase):
+ def __init__(self, name, args):
+ self.name = name
+ self.args = args
+
+ def __unicode__(self):
+ res = [self.name]
+ if self.args:
+ res.append('(')
+ res.append(text_type(self.args))
+ res.append(')')
+ return ''.join(res)
+
+
+class ASTGnuAttributeList(ASTBase):
+ def __init__(self, attrs):
+ self.attrs = attrs
+
+ def __unicode__(self):
+ res = ['__attribute__((']
+ first = True
+ for attr in self.attrs:
+ if not first:
+ res.append(', ')
+ first = False
+ res.append(text_type(attr))
+ res.append('))')
+ return ''.join(res)
+
+ def describe_signature(self, signode):
+ txt = text_type(self)
+ signode.append(nodes.Text(txt, txt))
+
+
+class ASTIdAttribute(ASTBase):
+ """For simple attributes defined by the user."""
+
+ def __init__(self, id):
+ self.id = id
+
+ def __unicode__(self):
+ return self.id
+
+ def describe_signature(self, signode):
+ signode.append(nodes.Text(self.id, self.id))
+
+
+class ASTParenAttribute(ASTBase):
+ """For paren attributes defined by the user."""
+
+ def __init__(self, id, arg):
+ self.id = id
+ self.arg = arg
+
+ def __unicode__(self):
+ return self.id + '(' + self.arg + ')'
+
+ def describe_signature(self, signode):
+ txt = text_type(self)
+ signode.append(nodes.Text(txt, txt))
+
+
class ASTIdentifier(ASTBase):
def __init__(self, identifier):
assert identifier is not None
@@ -1341,7 +1415,7 @@ class ASTParametersQualifiers(ASTBase):
class ASTDeclSpecsSimple(ASTBase):
def __init__(self, storage, threadLocal, inline, virtual, explicit,
- constexpr, volatile, const, friend):
+ constexpr, volatile, const, friend, attrs):
self.storage = storage
self.threadLocal = threadLocal
self.inline = inline
@@ -1351,6 +1425,7 @@ class ASTDeclSpecsSimple(ASTBase):
self.volatile = volatile
self.const = const
self.friend = friend
+ self.attrs = attrs
def mergeWith(self, other):
if not other:
@@ -1363,10 +1438,12 @@ class ASTDeclSpecsSimple(ASTBase):
self.constexpr or other.constexpr,
self.volatile or other.volatile,
self.const or other.const,
- self.friend or other.friend)
+ self.friend or other.friend,
+ self.attrs + other.attrs)
def __unicode__(self):
res = []
+ res.extend(text_type(attr) for attr in self.attrs)
if self.storage:
res.append(self.storage)
if self.threadLocal:
@@ -1392,6 +1469,10 @@ class ASTDeclSpecsSimple(ASTBase):
if len(modifiers) > 0:
modifiers.append(nodes.Text(' '))
modifiers.append(addnodes.desc_annotation(text, text))
+ for attr in self.attrs:
+ if len(modifiers) > 0:
+ modifiers.append(nodes.Text(' '))
+ modifiers.append(attr.describe_signature(modifiers))
if self.storage:
_add(modifiers, self.storage)
if self.threadLocal:
@@ -2062,7 +2143,7 @@ class ASTTypeWithInit(ASTBase):
def get_id_v2(self, objectType=None, symbol=None):
if objectType == 'member':
- return symbol.declaration.name.get_id_v2()
+ return symbol.get_full_nested_name().get_id_v2()
else:
return self.type.get_id_v2()
@@ -2780,6 +2861,10 @@ class Symbol(object):
if symbol is None:
# TODO: maybe search without template args
return None
+ # We have now matched part of a nested name, and need to match more
+ # so even if we should matchSelf before, we definitely shouldn't
+ # even more. (see also issue #2666)
+ matchSelf = False
parentSymbol = symbol
assert False # should have returned in the loop
@@ -2825,7 +2910,7 @@ class DefinitionParser(object):
_prefix_keys = ('class', 'struct', 'enum', 'union', 'typename')
- def __init__(self, definition, warnEnv):
+ def __init__(self, definition, warnEnv, config):
self.definition = definition.strip()
self.pos = 0
self.end = len(self.definition)
@@ -2833,6 +2918,7 @@ class DefinitionParser(object):
self._previous_state = (0, None)
self.warnEnv = warnEnv
+ self.config = config
def _make_multi_error(self, errors, header):
if len(errors) == 1:
@@ -2901,6 +2987,12 @@ class DefinitionParser(object):
return True
return False
+ def skip_string_and_ws(self, string):
+ if self.skip_string(string):
+ self.skip_ws()
+ return True
+ return False
+
@property
def eof(self):
return self.pos >= self.end
@@ -2927,6 +3019,85 @@ class DefinitionParser(object):
if not self.eof:
self.fail('Expected end of definition.')
+ def _parse_balanced_token_seq(self, end):
+ # TODO: add handling of string literals and similar
+ brackets = {'(': ')', '[': ']', '{': '}'}
+ startPos = self.pos
+ symbols = []
+ while not self.eof:
+ if len(symbols) == 0 and self.current_char in end:
+ break
+ if self.current_char in brackets.keys():
+ symbols.append(brackets[self.current_char])
+ elif len(symbols) > 0 and self.current_char == symbols[-1]:
+ symbols.pop()
+ elif self.current_char in ")]}":
+ self.fail("Unexpected '%s' in balanced-token-seq." % self.current_char)
+ self.pos += 1
+ if self.eof:
+ self.fail("Could not find end of balanced-token-seq starting at %d."
+ % startPos)
+ return self.definition[startPos:self.pos]
+
+ def _parse_attribute(self):
+ self.skip_ws()
+ # try C++11 style
+ startPos = self.pos
+ if self.skip_string_and_ws('['):
+ if not self.skip_string('['):
+ self.pos = startPos
+ else:
+ # TODO: actually implement the correct grammar
+ arg = self._parse_balanced_token_seq(end=[']'])
+ if not self.skip_string_and_ws(']'):
+ self.fail("Expected ']' in end of attribute.")
+ if not self.skip_string_and_ws(']'):
+ self.fail("Expected ']' in end of attribute after [[...]")
+ return ASTCPPAttribute(arg)
+
+ # try GNU style
+ if self.skip_word_and_ws('__attribute__'):
+ if not self.skip_string_and_ws('('):
+ self.fail("Expected '(' after '__attribute__'.")
+ if not self.skip_string_and_ws('('):
+ self.fail("Expected '(' after '__attribute__('.")
+ attrs = []
+ while 1:
+ if self.match(_identifier_re):
+ name = self.matched_text
+ self.skip_ws()
+ if self.skip_string_and_ws('('):
+ self.fail('Parameterized GNU style attribute not yet supported.')
+ attrs.append(ASTGnuAttribute(name, None))
+ # TODO: parse arguments for the attribute
+ if self.skip_string_and_ws(','):
+ continue
+ elif self.skip_string_and_ws(')'):
+ break
+ else:
+ self.fail("Expected identifier, ')', or ',' in __attribute__.")
+ if not self.skip_string_and_ws(')'):
+ self.fail("Expected ')' after '__attribute__((...)'")
+ return ASTGnuAttributeList(attrs)
+
+ # try the simple id attributes defined by the user
+ for id in self.config.cpp_id_attributes:
+ if self.skip_word_and_ws(id):
+ return ASTIdAttribute(id)
+
+ # try the paren attributes defined by the user
+ for id in self.config.cpp_paren_attributes:
+ if not self.skip_string_and_ws(id):
+ continue
+ if not self.skip_string('('):
+ self.fail("Expected '(' after user-defined paren-attribute.")
+ arg = self._parse_balanced_token_seq(end=[')'])
+ if not self.skip_string(')'):
+ self.fail("Expected ')' to end user-defined paren-attribute.")
+ return ASTParenAttribute(id, arg)
+
+ return None
+
def _parse_expression(self, end):
# Stupidly "parse" an expression.
# 'end' should be a list of characters which ends the expression.
@@ -3127,10 +3298,9 @@ class DefinitionParser(object):
self.fail('Expected ")" after "..." in '
'parameters_and_qualifiers.')
break
- if paramMode == 'function':
- arg = self._parse_type_with_init(outer=None, named='single')
- else:
- arg = self._parse_type(named=False)
+ # note: it seems that function arguments can always sbe named,
+ # even in function pointers and similar.
+ arg = self._parse_type_with_init(outer=None, named='single')
# TODO: parse default parameters # TODO: didn't we just do that?
args.append(ASTFunctinoParameter(arg))
@@ -3209,6 +3379,7 @@ class DefinitionParser(object):
volatile = None
const = None
friend = None
+ attrs = []
while 1: # accept any permutation of a subset of some decl-specs
self.skip_ws()
if not storage:
@@ -3262,9 +3433,14 @@ class DefinitionParser(object):
const = self.skip_word('const')
if const:
continue
+ attr = self._parse_attribute()
+ if attr:
+ attrs.append(attr)
+ continue
break
return ASTDeclSpecsSimple(storage, threadLocal, inline, virtual,
- explicit, constexpr, volatile, const, friend)
+ explicit, constexpr, volatile, const,
+ friend, attrs)
def _parse_decl_specs(self, outer, typed=True):
if outer:
@@ -3921,7 +4097,7 @@ class CPPObject(ObjectDescription):
id_v1 = None
id_v2 = ast.get_id_v2()
# store them in reverse order, so the newest is first
- ids = [id_v2, id_v1]
+ ids = [id_v2, id_v1]
newestId = ids[0]
assert newestId # shouldn't be None
@@ -3930,7 +4106,12 @@ class CPPObject(ObjectDescription):
'report as bug (id=%s).' % (text_type(ast), newestId))
name = text_type(ast.symbol.get_full_nested_name()).lstrip(':')
- indexText = self.get_index_text(name)
+ strippedName = name
+ for prefix in self.env.config.cpp_index_common_prefix:
+ if name.startswith(prefix):
+ strippedName = strippedName[len(prefix):]
+ break
+ indexText = self.get_index_text(strippedName)
self.indexnode['entries'].append(('single', indexText, newestId, '', None))
if newestId not in self.state.document.ids:
@@ -3942,8 +4123,14 @@ class CPPObject(ObjectDescription):
else:
# print("[CPP] non-unique name:", name)
pass
- for id in ids:
- if id: # is None when the element didn't exist in that version
+ # always add the newest id
+ assert newestId
+ signode['ids'].append(newestId)
+ # only add compatibility ids when there are no conflicts
+ for id in ids[1:]:
+ if not id: # is None when the element didn't exist in that version
+ continue
+ if id not in self.state.document.ids:
signode['ids'].append(id)
signode['first'] = (not self.names) # hmm, what is this abound?
self.state.document.note_explicit_target(signode)
@@ -3969,7 +4156,7 @@ class CPPObject(ObjectDescription):
self.env.ref_context['cpp:parent_symbol'] = root
parentSymbol = self.env.ref_context['cpp:parent_symbol']
- parser = DefinitionParser(sig, self)
+ parser = DefinitionParser(sig, self, self.env.config)
try:
ast = self.parse_definition(parser)
parser.assert_end()
@@ -3996,6 +4183,15 @@ class CPPObject(ObjectDescription):
self.describe_signature(signode, ast)
return ast
+ def before_content(self):
+ lastSymbol = self.env.ref_context['cpp:last_symbol']
+ assert lastSymbol
+ self.oldParentSymbol = self.env.ref_context['cpp:parent_symbol']
+ self.env.ref_context['cpp:parent_symbol'] = lastSymbol
+
+ def after_content(self):
+ self.env.ref_context['cpp:parent_symbol'] = self.oldParentSymbol
+
class CPPTypeObject(CPPObject):
def get_index_text(self, name):
@@ -4106,7 +4302,7 @@ class CPPNamespaceObject(Directive):
symbol = rootSymbol
stack = []
else:
- parser = DefinitionParser(self.arguments[0], self)
+ parser = DefinitionParser(self.arguments[0], self, env.config)
try:
ast = parser.parse_namespace_object()
parser.assert_end()
@@ -4135,7 +4331,7 @@ class CPPNamespacePushObject(Directive):
env = self.state.document.settings.env
if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
return
- parser = DefinitionParser(self.arguments[0], self)
+ parser = DefinitionParser(self.arguments[0], self, env.config)
try:
ast = parser.parse_namespace_object()
parser.assert_end()
@@ -4285,7 +4481,7 @@ class CPPDomain(Domain):
if emitWarnings:
env.warn_node(msg, node)
warner = Warner()
- parser = DefinitionParser(target, warner)
+ parser = DefinitionParser(target, warner, env.config)
try:
ast = parser.parse_xref_object()
parser.skip_ws()
@@ -4315,6 +4511,31 @@ class CPPDomain(Domain):
matchSelf=True)
if s is None or s.declaration is None:
return None, None
+
+ if typ.startswith('cpp:'):
+ typ = typ[4:]
+ if typ == 'func':
+ typ = 'function'
+ declTyp = s.declaration.objectType
+
+ def checkType():
+ if typ == 'any':
+ return True
+ if declTyp == 'templateParam':
+ return True
+ if typ == 'var' or typ == 'member':
+ return declTyp in ['var', 'member']
+ if typ in ['enum', 'enumerator', 'function', 'class']:
+ return declTyp == typ
+ if typ == 'type':
+ return declTyp in ['enum', 'class', 'function', 'type']
+ print("Type is %s" % typ)
+ assert False
+ if not checkType():
+ warner.warn("cpp:%s targets a %s (%s)."
+ % (typ, s.declaration.objectType,
+ s.get_full_nested_name()))
+
declaration = s.declaration
fullNestedName = s.get_full_nested_name()
name = text_type(fullNestedName).lstrip(':')
@@ -4354,3 +4575,10 @@ class CPPDomain(Domain):
docname = symbol.docname
newestId = symbol.declaration.get_newest_id()
yield (name, name, objectType, docname, newestId, 1)
+
+
+def setup(app):
+ app.add_domain(CPPDomain)
+ app.add_config_value("cpp_index_common_prefix", [], 'env')
+ app.add_config_value("cpp_id_attributes", [], 'env')
+ app.add_config_value("cpp_paren_attributes", [], 'env')
diff --git a/sphinx/domains/javascript.py b/sphinx/domains/javascript.py
index b5f64022a..ade6e4224 100644
--- a/sphinx/domains/javascript.py
+++ b/sphinx/domains/javascript.py
@@ -234,3 +234,7 @@ class JavaScriptDomain(Domain):
for refname, (docname, type) in list(self.data['objects'].items()):
yield refname, refname, type, docname, \
refname.replace('$', '_S_'), 1
+
+
+def setup(app):
+ app.add_domain(JavaScriptDomain)
diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py
index 1639d8288..3d7e10467 100644
--- a/sphinx/domains/python.py
+++ b/sphinx/domains/python.py
@@ -101,11 +101,36 @@ class PyXrefMixin(object):
break
return result
+ def make_xrefs(self, rolename, domain, target, innernode=nodes.emphasis,
+ contnode=None):
+ delims = '(\s*[\[\]\(\),]\s*)'
+ delims_re = re.compile(delims)
+ sub_targets = re.split(delims, target)
+
+ split_contnode = bool(contnode and contnode.astext() == target)
+
+ results = []
+ for sub_target in sub_targets:
+ if split_contnode:
+ contnode = nodes.Text(sub_target)
+
+ if delims_re.match(sub_target):
+ results.append(contnode or innernode(sub_target, sub_target))
+ else:
+ results.append(self.make_xref(rolename, domain, sub_target,
+ innernode, contnode))
+
+ return results
+
class PyField(PyXrefMixin, Field):
pass
+class PyGroupedField(PyXrefMixin, GroupedField):
+ pass
+
+
class PyTypedField(PyXrefMixin, TypedField):
pass
@@ -130,9 +155,9 @@ class PyObject(ObjectDescription):
names=('var', 'ivar', 'cvar'),
typerolename='obj', typenames=('vartype',),
can_collapse=True),
- GroupedField('exceptions', label=l_('Raises'), rolename='exc',
- names=('raises', 'raise', 'exception', 'except'),
- can_collapse=True),
+ PyGroupedField('exceptions', label=l_('Raises'), rolename='exc',
+ names=('raises', 'raise', 'exception', 'except'),
+ can_collapse=True),
Field('returnvalue', label=l_('Returns'), has_arg=False,
names=('returns', 'return')),
PyField('returntype', label=l_('Return type'), has_arg=False,
@@ -771,3 +796,7 @@ class PythonDomain(Domain):
for refname, (docname, type) in iteritems(self.data['objects']):
if type != 'module': # modules are already handled
yield (refname, refname, type, docname, refname, 1)
+
+
+def setup(app):
+ app.add_domain(PythonDomain)
diff --git a/sphinx/domains/rst.py b/sphinx/domains/rst.py
index b11c9450b..526ae18a7 100644
--- a/sphinx/domains/rst.py
+++ b/sphinx/domains/rst.py
@@ -156,3 +156,7 @@ class ReSTDomain(Domain):
def get_objects(self):
for (typ, name), docname in iteritems(self.data['objects']):
yield name, name, typ, docname, typ + '-' + name, 1
+
+
+def setup(app):
+ app.add_domain(ReSTDomain)
diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py
index 997d95ba3..001d9f6d9 100644
--- a/sphinx/domains/std.py
+++ b/sphinx/domains/std.py
@@ -14,7 +14,6 @@ import unicodedata
from six import iteritems
from docutils import nodes
-from docutils.nodes import fully_normalize_name
from docutils.parsers.rst import directives
from docutils.statemachine import ViewList
@@ -585,106 +584,119 @@ class StandardDomain(Domain):
newnode.append(innernode)
return newnode
- def resolve_xref(self, env, fromdocname, builder,
- typ, target, node, contnode):
+ def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
if typ == 'ref':
- if node['refexplicit']:
- # reference to anonymous label; the reference uses
- # the supplied link caption
- docname, labelid = self.data['anonlabels'].get(target, ('', ''))
- sectname = node.astext()
- else:
- # reference to named label; the final node will
- # contain the section name after the label
- docname, labelid, sectname = self.data['labels'].get(target,
- ('', '', ''))
- if not docname:
- return None
-
- return self.build_reference_node(fromdocname, builder,
- docname, labelid, sectname, 'ref')
+ resolver = self._resolve_ref_xref
elif typ == 'numref':
- docname, labelid = self.data['anonlabels'].get(target, ('', ''))
- if not docname:
- return None
-
- if env.config.numfig is False:
- env.warn(fromdocname, 'numfig is disabled. :numref: is ignored.',
- lineno=node.line)
- return contnode
+ resolver = self._resolve_numref_xref
+ elif typ == 'keyword':
+ resolver = self._resolve_keyword_xref
+ elif typ == 'option':
+ resolver = self._resolve_option_xref
+ else:
+ resolver = self._resolve_obj_xref
- target_node = env.get_doctree(docname).ids.get(labelid)
- figtype = self.get_figtype(target_node)
- if figtype is None:
- return None
+ return resolver(env, fromdocname, builder, typ, target, node, contnode)
- try:
- figure_id = target_node['ids'][0]
- fignumber = env.toc_fignumbers[docname][figtype][figure_id]
- except (KeyError, IndexError):
- # target_node is found, but fignumber is not assigned.
- # Maybe it is defined in orphaned document.
- env.warn(fromdocname, "no number is assigned for %s: %s" % (figtype, labelid),
- lineno=node.line)
- return contnode
-
- title = contnode.astext()
- if target == fully_normalize_name(title):
+ def _resolve_ref_xref(self, env, fromdocname, builder, typ, target, node, contnode):
+ if node['refexplicit']:
+ # reference to anonymous label; the reference uses
+ # the supplied link caption
+ docname, labelid = self.data['anonlabels'].get(target, ('', ''))
+ sectname = node.astext()
+ else:
+ # reference to named label; the final node will
+ # contain the section name after the label
+ docname, labelid, sectname = self.data['labels'].get(target,
+ ('', '', ''))
+ if not docname:
+ return None
+
+ return self.build_reference_node(fromdocname, builder,
+ docname, labelid, sectname, 'ref')
+
+ def _resolve_numref_xref(self, env, fromdocname, builder, typ, target, node, contnode):
+ docname, labelid = self.data['anonlabels'].get(target, ('', ''))
+ if not docname:
+ return None
+
+ if env.config.numfig is False:
+ env.warn_node('numfig is disabled. :numref: is ignored.', node)
+ return contnode
+
+ target_node = env.get_doctree(docname).ids.get(labelid)
+ figtype = self.get_figtype(target_node)
+ if figtype is None:
+ return None
+
+ try:
+ figure_id = target_node['ids'][0]
+ fignumber = env.toc_fignumbers[docname][figtype][figure_id]
+ except (KeyError, IndexError):
+ # target_node is found, but fignumber is not assigned.
+ # Maybe it is defined in orphaned document.
+ env.warn_node("no number is assigned for %s: %s" % (figtype, labelid), node)
+ return contnode
+
+ try:
+ if node['refexplicit']:
+ title = contnode.astext()
+ else:
title = env.config.numfig_format.get(figtype, '')
- try:
- newtitle = title % '.'.join(map(str, fignumber))
- except TypeError:
- env.warn(fromdocname, 'invalid numfig_format: %s' % title,
- lineno=node.line)
+ newtitle = title % '.'.join(map(str, fignumber))
+ except TypeError:
+ env.warn_node('invalid numfig_format: %s' % title, node)
+ return None
+
+ return self.build_reference_node(fromdocname, builder,
+ docname, labelid, newtitle, 'numref',
+ nodeclass=addnodes.number_reference,
+ title=title)
+
+ def _resolve_keyword_xref(self, env, fromdocname, builder, typ, target, node, contnode):
+ # keywords are oddballs: they are referenced by named labels
+ docname, labelid, _ = self.data['labels'].get(target, ('', '', ''))
+ if not docname:
+ return None
+ return make_refnode(builder, fromdocname, docname,
+ labelid, contnode)
+
+ def _resolve_option_xref(self, env, fromdocname, builder, typ, target, node, contnode):
+ progname = node.get('std:program')
+ target = target.strip()
+ docname, labelid = self.data['progoptions'].get((progname, target), ('', ''))
+ if not docname:
+ commands = []
+ while ws_re.search(target):
+ subcommand, target = ws_re.split(target, 1)
+ commands.append(subcommand)
+ progname = "-".join(commands)
+
+ docname, labelid = self.data['progoptions'].get((progname, target),
+ ('', ''))
+ if docname:
+ break
+ else:
return None
- return self.build_reference_node(fromdocname, builder,
- docname, labelid, newtitle, 'numref',
- nodeclass=addnodes.number_reference,
- title=title)
- elif typ == 'keyword':
- # keywords are oddballs: they are referenced by named labels
- docname, labelid, _ = self.data['labels'].get(target, ('', '', ''))
- if not docname:
- return None
- return make_refnode(builder, fromdocname, docname,
- labelid, contnode)
- elif typ == 'option':
- progname = node.get('std:program')
- target = target.strip()
- docname, labelid = self.data['progoptions'].get((progname, target), ('', ''))
- if not docname:
- commands = []
- while ws_re.search(target):
- subcommand, target = ws_re.split(target, 1)
- commands.append(subcommand)
- progname = "-".join(commands)
-
- docname, labelid = self.data['progoptions'].get((progname, target),
- ('', ''))
- if docname:
- break
- else:
- return None
+ return make_refnode(builder, fromdocname, docname,
+ labelid, contnode)
- return make_refnode(builder, fromdocname, docname,
- labelid, contnode)
+ def _resolve_obj_xref(self, env, fromdocname, builder, typ, target, node, contnode):
+ objtypes = self.objtypes_for_role(typ) or []
+ for objtype in objtypes:
+ if (objtype, target) in self.data['objects']:
+ docname, labelid = self.data['objects'][objtype, target]
+ break
else:
- objtypes = self.objtypes_for_role(typ) or []
- for objtype in objtypes:
- if (objtype, target) in self.data['objects']:
- docname, labelid = self.data['objects'][objtype, target]
- break
- else:
- docname, labelid = '', ''
- if not docname:
- return None
- return make_refnode(builder, fromdocname, docname,
- labelid, contnode)
+ docname, labelid = '', ''
+ if not docname:
+ return None
+ return make_refnode(builder, fromdocname, docname,
+ labelid, contnode)
- def resolve_any_xref(self, env, fromdocname, builder, target,
- node, contnode):
+ def resolve_any_xref(self, env, fromdocname, builder, target, node, contnode):
results = []
ltarget = target.lower() # :ref: lowercases its target automatically
for role in ('ref', 'option'): # do not try "keyword"
@@ -755,3 +767,7 @@ class StandardDomain(Domain):
else:
figtype, _ = self.enumerable_nodes.get(node.__class__, (None, None))
return figtype
+
+
+def setup(app):
+ app.add_domain(StandardDomain)
diff --git a/sphinx/environment.py b/sphinx/environment.py
index 92064f911..e31ebea47 100644
--- a/sphinx/environment.py
+++ b/sphinx/environment.py
@@ -17,6 +17,7 @@ import types
import bisect
import codecs
import string
+import fnmatch
import unicodedata
from os import path
from glob import glob
@@ -75,7 +76,7 @@ default_settings = {
# or changed to properly invalidate pickle files.
#
# NOTE: increase base version by 2 to have distinct numbers for Py2 and 3
-ENV_VERSION = 48 + (sys.version_info[0] - 2)
+ENV_VERSION = 49 + (sys.version_info[0] - 2)
dummy_reporter = Reporter('', 4, 4)
@@ -169,6 +170,7 @@ class BuildEnvironment:
# contains all read docnames
self.dependencies = {} # docname -> set of dependent file
# names, relative to documentation root
+ self.included = set() # docnames included from other documents
self.reread_always = set() # docnames to re-read unconditionally on
# next build
@@ -328,6 +330,20 @@ class BuildEnvironment:
domain.merge_domaindata(docnames, other.domaindata[domainname])
app.emit('env-merge-info', self, docnames, other)
+ def path2doc(self, filename):
+ """Return the docname for the filename if the file is document.
+
+ *filename* should be absolute or relative to the source directory.
+ """
+ if filename.startswith(self.srcdir):
+ filename = filename[len(self.srcdir) + 1:]
+ for suffix in self.config.source_suffix:
+ if fnmatch.fnmatch(filename, '*' + suffix):
+ return filename[:-len(suffix)]
+ else:
+ # the file does not have docname
+ return None
+
def doc2path(self, docname, base=True, suffix=None):
"""Return the filename for the document name.
@@ -387,8 +403,13 @@ class BuildEnvironment:
config.html_extra_path +
['**/_sources', '.#*', '**/.#*', '*.lproj/**']
)
- self.found_docs = set(get_matching_docs(
- self.srcdir, config.source_suffix, exclude_matchers=matchers))
+ self.found_docs = set()
+ for docname in get_matching_docs(self.srcdir, config.source_suffix,
+ exclude_matchers=matchers):
+ if os.access(self.doc2path(docname), os.R_OK):
+ self.found_docs.add(docname)
+ else:
+ self.warn(docname, "document not readable. Ignored.")
# add catalog mo file dependency
for docname in self.found_docs:
@@ -820,6 +841,15 @@ class BuildEnvironment:
"""
self.dependencies.setdefault(self.docname, set()).add(filename)
+ def note_included(self, filename):
+ """Add *filename* as a included from other document.
+
+ This means the document is not orphaned.
+
+ *filename* should be absolute or relative to the source directory.
+ """
+ self.included.add(self.path2doc(filename))
+
def note_reread(self):
"""Add the current document to the list of documents that will
automatically be re-read at the next build.
@@ -1413,7 +1443,10 @@ class BuildEnvironment:
# nodes with length 1 don't have any children anyway
if len(toplevel) > 1:
subtrees = toplevel.traverse(addnodes.toctree)
- toplevel[1][:] = subtrees
+ if subtrees:
+ toplevel[1][:] = subtrees
+ else:
+ toplevel.pop(1)
# resolve all sub-toctrees
for subtocnode in toc.traverse(addnodes.toctree):
if not (subtocnode.get('hidden', False) and
@@ -1459,6 +1492,9 @@ class BuildEnvironment:
_toctree_add_classes(newnode, 1)
self._toctree_prune(newnode, 1, prune and maxdepth or 0, collapse)
+ if len(newnode[-1]) == 0: # No titles found
+ return None
+
# set the target paths in the toctrees (they are not known at TOC
# generation time)
for refnode in newnode.traverse(nodes.reference):
@@ -1488,9 +1524,9 @@ class BuildEnvironment:
typ, target, node, contnode)
# really hardwired reference types
elif typ == 'any':
- newnode = self._resolve_any_reference(builder, node, contnode)
+ newnode = self._resolve_any_reference(builder, refdoc, node, contnode)
elif typ == 'doc':
- newnode = self._resolve_doc_reference(builder, node, contnode)
+ newnode = self._resolve_doc_reference(builder, refdoc, node, contnode)
elif typ == 'citation':
newnode = self._resolve_citation(builder, refdoc, node, contnode)
# no new node found? try the missing-reference event
@@ -1538,10 +1574,10 @@ class BuildEnvironment:
msg = '%r reference target not found: %%(target)s' % typ
self.warn_node(msg % {'target': target}, node, type='ref', subtype=typ)
- def _resolve_doc_reference(self, builder, node, contnode):
+ def _resolve_doc_reference(self, builder, refdoc, node, contnode):
# directly reference to document by source name;
# can be absolute or relative
- docname = docname_join(node['refdoc'], node['reftarget'])
+ docname = docname_join(refdoc, node['reftarget'])
if docname in self.all_docs:
if node['refexplicit']:
# reference with explicit title
@@ -1551,7 +1587,7 @@ class BuildEnvironment:
innernode = nodes.inline(caption, caption)
innernode['classes'].append('doc')
newnode = nodes.reference('', '', internal=True)
- newnode['refuri'] = builder.get_relative_uri(node['refdoc'], docname)
+ newnode['refuri'] = builder.get_relative_uri(refdoc, docname)
newnode.append(innernode)
return newnode
@@ -1574,13 +1610,12 @@ class BuildEnvironment:
# transforms.CitationReference.apply.
del node['ids'][:]
- def _resolve_any_reference(self, builder, node, contnode):
+ def _resolve_any_reference(self, builder, refdoc, node, contnode):
"""Resolve reference generated by the "any" role."""
- refdoc = node['refdoc']
target = node['reftarget']
results = []
# first, try resolving as :doc:
- doc_ref = self._resolve_doc_reference(builder, node, contnode)
+ doc_ref = self._resolve_doc_reference(builder, refdoc, node, contnode)
if doc_ref:
results.append(('doc', doc_ref))
# next, do the standard domain (makes this a priority)
@@ -1931,6 +1966,9 @@ class BuildEnvironment:
if docname == self.config.master_doc:
# the master file is not included anywhere ;)
continue
+ if docname in self.included:
+ # the document is included from other documents
+ continue
if 'orphan' in self.metadata[docname]:
continue
self.warn(docname, 'document isn\'t included in any toctree')
diff --git a/sphinx/errors.py b/sphinx/errors.py
index 8d695c190..5fb77a135 100644
--- a/sphinx/errors.py
+++ b/sphinx/errors.py
@@ -67,7 +67,10 @@ class PycodeError(Exception):
return res
-class SphinxParallelError(Exception):
+class SphinxParallelError(SphinxError):
+
+ category = 'Sphinx parallel build error'
+
def __init__(self, orig_exc, traceback):
self.orig_exc = orig_exc
self.traceback = traceback
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py
index 6ae0966fb..08bc99cdf 100644
--- a/sphinx/ext/autodoc.py
+++ b/sphinx/ext/autodoc.py
@@ -261,12 +261,13 @@ def format_annotation(annotation):
Displaying complex types from ``typing`` relies on its private API.
"""
+ if not isinstance(annotation, type):
+ return repr(annotation)
+
qualified_name = (annotation.__module__ + '.' + annotation.__qualname__
if annotation else repr(annotation))
- if not isinstance(annotation, type):
- return repr(annotation)
- elif annotation.__module__ == 'builtins':
+ if annotation.__module__ == 'builtins':
return annotation.__qualname__
elif typing:
if isinstance(annotation, typing.TypeVar):
diff --git a/sphinx/ext/imgmath.py b/sphinx/ext/imgmath.py
index f8e402be3..e5b8b26c5 100644
--- a/sphinx/ext/imgmath.py
+++ b/sphinx/ext/imgmath.py
@@ -22,6 +22,7 @@ from six import text_type
from docutils import nodes
import sphinx
+from sphinx.locale import _
from sphinx.errors import SphinxError, ExtensionError
from sphinx.util.png import read_png_depth, write_png_depth
from sphinx.util.osutil import ensuredir, ENOENT, cd
@@ -253,7 +254,9 @@ def html_visit_displaymath(self, node):
self.body.append(self.starttag(node, 'div', CLASS='math'))
self.body.append('<p>')
if node['number']:
- self.body.append('<span class="eqno">(%s)</span>' % node['number'])
+ self.body.append('<span class="eqno">(%s)' % node['number'])
+ self.add_permalink_ref(node, _('Permalink to this equation'))
+ self.body.append('</span>')
if fname is None:
# something failed -- use text-only as a bad substitute
self.body.append('<span class="math">%s</span></p>\n</div>' %
diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py
index 8e6573e8a..c43b8ae6a 100644
--- a/sphinx/ext/intersphinx.py
+++ b/sphinx/ext/intersphinx.py
@@ -34,7 +34,8 @@ from os import path
import re
from six import iteritems, string_types
-from six.moves.urllib import parse, request
+from six.moves.urllib import request
+from six.moves.urllib.parse import urlsplit, urlunsplit
from docutils import nodes
from docutils.utils import relative_path
@@ -105,7 +106,7 @@ def read_inventory_v2(f, uri, join, bufsize=16*1024):
for line in split_lines(read_chunks()):
# be careful to handle names with embedded spaces correctly
- m = re.match(r'(?x)(.+?)\s+(\S*:\S*)\s+(\S+)\s+(\S+)\s+(.*)',
+ m = re.match(r'(?x)(.+?)\s+(\S*:\S*)\s+(-?\d+)\s+(\S+)\s+(.*)',
line.rstrip())
if not m:
continue
@@ -145,7 +146,7 @@ def _strip_basic_auth(url):
:rtype: ``tuple``
"""
- url_parts = parse.urlsplit(url)
+ url_parts = urlsplit(url)
username = url_parts.username
password = url_parts.password
frags = list(url_parts)
@@ -154,7 +155,7 @@ def _strip_basic_auth(url):
frags[1] = "%s:%s" % (url_parts.hostname, url_parts.port)
else:
frags[1] = url_parts.hostname
- url = parse.urlunsplit(frags)
+ url = urlunsplit(frags)
return (url, username, password)
@@ -208,12 +209,12 @@ def _get_safe_url(url):
url, username, _ = _strip_basic_auth(url)
if username is not None:
# case: url contained basic auth creds; obscure password
- url_parts = parse.urlsplit(url)
+ url_parts = urlsplit(url)
safe_netloc = '{0}@{1}'.format(username, url_parts.hostname)
# replace original netloc w/ obscured version
frags = list(url_parts)
frags[1] = safe_netloc
- safe_url = parse.urlunsplit(frags)
+ safe_url = urlunsplit(frags)
return safe_url
@@ -237,6 +238,13 @@ def fetch_inventory(app, uri, inv):
'%s: %s' % (inv, err.__class__, err))
return
try:
+ if hasattr(f, 'geturl'):
+ newuri = f.geturl()
+ if newuri.endswith("/" + INVENTORY_FILENAME):
+ newuri = newuri[:-len(INVENTORY_FILENAME) - 1]
+ if uri != newuri and uri != newuri + "/":
+ app.info('intersphinx inventory has moved: %s -> %s' % (uri, newuri))
+ uri = newuri
line = f.readline().rstrip().decode('utf-8')
try:
if line == '# Sphinx inventory version 1':
diff --git a/sphinx/ext/jsmath.py b/sphinx/ext/jsmath.py
index f36e12fed..9981ffd3a 100644
--- a/sphinx/ext/jsmath.py
+++ b/sphinx/ext/jsmath.py
@@ -13,6 +13,7 @@
from docutils import nodes
import sphinx
+from sphinx.locale import _
from sphinx.application import ExtensionError
from sphinx.ext.mathbase import setup_math as mathbase_setup
@@ -34,8 +35,9 @@ def html_visit_displaymath(self, node):
if i == 0:
# necessary to e.g. set the id property correctly
if node['number']:
- self.body.append('<span class="eqno">(%s)</span>' %
- node['number'])
+ self.body.append('<span class="eqno">(%s)' % node['number'])
+ self.add_permalink_ref(node, _('Permalink to this equation'))
+ self.body.append('</span>')
self.body.append(self.starttag(node, 'div', CLASS='math'))
else:
# but only once!
diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py
index 13a560c0a..ddcec492c 100644
--- a/sphinx/ext/mathbase.py
+++ b/sphinx/ext/mathbase.py
@@ -58,7 +58,7 @@ def wrap_displaymath(math, label, numbering):
begin = r'\begin{align*}%s\!\begin{aligned}' % labeldef
end = r'\end{aligned}\end{align*}'
for part in parts:
- equations.append('%s\\\\\n' % part)
+ equations.append('%s\\\\\n' % part.strip())
return '%s\n%s%s' % (begin, ''.join(equations), end)
diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py
index bdaab55e0..2f414f4e7 100644
--- a/sphinx/ext/mathjax.py
+++ b/sphinx/ext/mathjax.py
@@ -14,6 +14,7 @@
from docutils import nodes
import sphinx
+from sphinx.locale import _
from sphinx.errors import ExtensionError
from sphinx.ext.mathbase import setup_math as mathbase_setup
@@ -35,7 +36,9 @@ def html_visit_displaymath(self, node):
# necessary to e.g. set the id property correctly
if node['number']:
- self.body.append('<span class="eqno">(%s)</span>' % node['number'])
+ self.body.append('<span class="eqno">(%s)' % node['number'])
+ self.add_permalink_ref(node, _('Permalink to this equation'))
+ self.body.append('</span>')
self.body.append(self.builder.config.mathjax_display[0])
parts = [prt for prt in node['latex'].split('\n\n') if prt.strip()]
if len(parts) > 1: # Add alignment if there are more than 1 equation
diff --git a/sphinx/ext/napoleon/__init__.py b/sphinx/ext/napoleon/__init__.py
index 9dedc15d7..651355c57 100644
--- a/sphinx/ext/napoleon/__init__.py
+++ b/sphinx/ext/napoleon/__init__.py
@@ -51,16 +51,17 @@ class Config(object):
Attributes
----------
- napoleon_google_docstring : bool, defaults to True
+ napoleon_google_docstring : :obj:`bool` (Defaults to True)
True to parse `Google style`_ docstrings. False to disable support
for Google style docstrings.
- napoleon_numpy_docstring : bool, defaults to True
+ napoleon_numpy_docstring : :obj:`bool` (Defaults to True)
True to parse `NumPy style`_ docstrings. False to disable support
for NumPy style docstrings.
- napoleon_include_init_with_doc : bool, defaults to False
- True to include init methods (i.e. ``__init___``) with
- docstrings in the documentation. False to fall back to Sphinx's
- default behavior.
+ napoleon_include_init_with_doc : :obj:`bool` (Defaults to False)
+ True to list ``__init___`` docstrings separately from the class
+ docstring. False to fall back to Sphinx's default behavior, which
+ considers the ``__init___`` docstring as part of the class
+ documentation.
**If True**::
@@ -72,7 +73,7 @@ class Config(object):
def __init__(self):
# This will NOT be included in the docs
- napoleon_include_private_with_doc : bool, defaults to False
+ napoleon_include_private_with_doc : :obj:`bool` (Defaults to False)
True to include private members (like ``_membername``) with docstrings
in the documentation. False to fall back to Sphinx's default behavior.
@@ -88,7 +89,7 @@ class Config(object):
# This will NOT be included in the docs
pass
- napoleon_include_special_with_doc : bool, defaults to False
+ napoleon_include_special_with_doc : :obj:`bool` (Defaults to False)
True to include special members (like ``__membername__``) with
docstrings in the documentation. False to fall back to Sphinx's
default behavior.
@@ -105,7 +106,7 @@ class Config(object):
# This will NOT be included in the docs
return unicode(self.__class__.__name__)
- napoleon_use_admonition_for_examples : bool, defaults to False
+ napoleon_use_admonition_for_examples : :obj:`bool` (Defaults to False)
True to use the ``.. admonition::`` directive for the **Example** and
**Examples** sections. False to use the ``.. rubric::`` directive
instead. One may look better than the other depending on what HTML
@@ -129,7 +130,7 @@ class Config(object):
This is just a quick example
- napoleon_use_admonition_for_notes : bool, defaults to False
+ napoleon_use_admonition_for_notes : :obj:`bool` (Defaults to False)
True to use the ``.. admonition::`` directive for **Notes** sections.
False to use the ``.. rubric::`` directive instead.
@@ -142,7 +143,7 @@ class Config(object):
--------
:attr:`napoleon_use_admonition_for_examples`
- napoleon_use_admonition_for_references : bool, defaults to False
+ napoleon_use_admonition_for_references : :obj:`bool` (Defaults to False)
True to use the ``.. admonition::`` directive for **References**
sections. False to use the ``.. rubric::`` directive instead.
@@ -150,7 +151,7 @@ class Config(object):
--------
:attr:`napoleon_use_admonition_for_examples`
- napoleon_use_ivar : bool, defaults to False
+ napoleon_use_ivar : :obj:`bool` (Defaults to False)
True to use the ``:ivar:`` role for instance variables. False to use
the ``.. attribute::`` directive instead.
@@ -174,7 +175,7 @@ class Config(object):
Description of `attr1`
- napoleon_use_param : bool, defaults to True
+ napoleon_use_param : :obj:`bool` (Defaults to True)
True to use a ``:param:`` role for each function parameter. False to
use a single ``:parameters:`` role for all the parameters.
@@ -201,21 +202,22 @@ class Config(object):
* **arg2** (*int, optional*) --
Description of `arg2`, defaults to 0
- napoleon_use_keyword : bool, defaults to True
+ napoleon_use_keyword : :obj:`bool` (Defaults to True)
True to use a ``:keyword:`` role for each function keyword argument.
False to use a single ``:keyword arguments:`` role for all the
keywords.
- This behaves similarly to :attr:`napoleon_use_param`. Note unlike docutils,
- ``:keyword:`` and ``:param:`` will not be treated the same way - there will
- be a separate "Keyword Arguments" section, rendered in the same fashion as
- "Parameters" section (type links created if possible)
+ This behaves similarly to :attr:`napoleon_use_param`. Note unlike
+ docutils, ``:keyword:`` and ``:param:`` will not be treated the same
+ way - there will be a separate "Keyword Arguments" section, rendered
+ in the same fashion as "Parameters" section (type links created if
+ possible)
See Also
--------
:attr:`napoleon_use_param`
- napoleon_use_rtype : bool, defaults to True
+ napoleon_use_rtype : :obj:`bool` (Defaults to True)
True to use the ``:rtype:`` role for the return type. False to output
the return type inline with the description.
@@ -295,20 +297,23 @@ def setup(app):
def _patch_python_domain():
- import sphinx.domains.python
- from sphinx.domains.python import PyTypedField
- import sphinx.locale
- l_ = sphinx.locale.lazy_gettext
- for doc_field in sphinx.domains.python.PyObject.doc_field_types:
- if doc_field.name == 'parameter':
- doc_field.names = ('param', 'parameter', 'arg', 'argument')
- break
- sphinx.domains.python.PyObject.doc_field_types.append(
- PyTypedField('keyword', label=l_('Keyword Arguments'),
- names=('keyword', 'kwarg', 'kwparam'),
- typerolename='obj', typenames=('paramtype', 'kwtype'),
- can_collapse=True),
- )
+ try:
+ from sphinx.domains.python import PyTypedField
+ except ImportError:
+ pass
+ else:
+ import sphinx.domains.python
+ import sphinx.locale
+ l_ = sphinx.locale.lazy_gettext
+ for doc_field in sphinx.domains.python.PyObject.doc_field_types:
+ if doc_field.name == 'parameter':
+ doc_field.names = ('param', 'parameter', 'arg', 'argument')
+ break
+ sphinx.domains.python.PyObject.doc_field_types.append(
+ PyTypedField('keyword', label=l_('Keyword Arguments'),
+ names=('keyword', 'kwarg', 'kwparam'),
+ typerolename='obj', typenames=('paramtype', 'kwtype'),
+ can_collapse=True))
def _process_docstring(app, what, name, obj, options, lines):
diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py
index c12b75e6d..e526a11ae 100644
--- a/sphinx/ext/napoleon/docstring.py
+++ b/sphinx/ext/napoleon/docstring.py
@@ -24,8 +24,9 @@ from sphinx.util.pycompat import UnicodeMixin
_directive_regex = re.compile(r'\.\. \S+::')
_google_section_regex = re.compile(r'^(\s|\w)+:\s*$')
-_google_typed_arg_regex = re.compile(r'\s*(.+?)\s*\(\s*(.+?)\s*\)')
+_google_typed_arg_regex = re.compile(r'\s*(.+?)\s*\(\s*(.*[^\s]+)\s*\)')
_numpy_section_regex = re.compile(r'^[=\-`:\'"~^_*+#<>]{2,}\s*$')
+_single_colon_regex = re.compile(r'(?<!:):(?!:)')
_xref_regex = re.compile(r'(:\w+:\S+:`.+?`|:\S+:`.+?`|`.+?`)')
_bullet_list_regex = re.compile(r'^(\*|\+|\-)(\s+\S|\s*$)')
_enumerated_list_regex = re.compile(
@@ -39,36 +40,34 @@ class GoogleDocstring(UnicodeMixin):
Parameters
----------
- docstring : str or List[str]
+ docstring : :obj:`str` or :obj:`list` of :obj:`str`
The docstring to parse, given either as a string or split into
individual lines.
- config : Optional[sphinx.ext.napoleon.Config or sphinx.config.Config]
+ config: :obj:`sphinx.ext.napoleon.Config` or :obj:`sphinx.config.Config`
The configuration settings to use. If not given, defaults to the
config object on `app`; or if `app` is not given defaults to the
- a new `sphinx.ext.napoleon.Config` object.
+ a new :class:`sphinx.ext.napoleon.Config` object.
- See Also
- --------
- :class:`sphinx.ext.napoleon.Config`
Other Parameters
----------------
- app : Optional[sphinx.application.Sphinx]
+ app : :class:`sphinx.application.Sphinx`, optional
Application object representing the Sphinx process.
- what : Optional[str]
+ what : :obj:`str`, optional
A string specifying the type of the object to which the docstring
belongs. Valid values: "module", "class", "exception", "function",
"method", "attribute".
- name : Optional[str]
+ name : :obj:`str`, optional
The fully qualified name of the object.
obj : module, class, exception, function, method, or attribute
The object to which the docstring belongs.
- options : Optional[sphinx.ext.autodoc.Options]
+ options : :class:`sphinx.ext.autodoc.Options`, optional
The options given to the directive: an object with attributes
inherited_members, undoc_members, show_inheritance and noindex that
are True if the flag option of same name was given to the auto
directive.
+
Example
-------
>>> from sphinx.ext.napoleon import Config
@@ -174,7 +173,7 @@ class GoogleDocstring(UnicodeMixin):
Returns
-------
- List[str]
+ list(str)
The lines of the docstring in a list.
"""
@@ -256,12 +255,7 @@ class GoogleDocstring(UnicodeMixin):
else:
_desc = lines[1:]
- match = _google_typed_arg_regex.match(before)
- if match:
- _name = match.group(1)
- _type = match.group(2)
- else:
- _type = before
+ _type = before
_desc = self.__class__(_desc, self._config).lines()
return [(_name, _type, _desc,)]
@@ -307,6 +301,19 @@ class GoogleDocstring(UnicodeMixin):
else:
return name
+ def _fix_field_desc(self, desc):
+ if self._is_list(desc):
+ desc = [''] + desc
+ elif desc[0].endswith('::'):
+ desc_block = desc[1:]
+ indent = self._get_indent(desc[0])
+ block_indent = self._get_initial_indent(desc_block)
+ if block_indent > indent:
+ desc = [''] + desc
+ else:
+ desc = ['', desc[0]] + self._indent(desc_block, 4)
+ return desc
+
def _format_admonition(self, admonition, lines):
lines = self._strip_empty(lines)
if len(lines) == 1:
@@ -333,6 +340,22 @@ class GoogleDocstring(UnicodeMixin):
else:
return [prefix]
+ def _format_docutils_params(self, fields, field_role='param',
+ type_role='type'):
+ lines = []
+ for _name, _type, _desc in fields:
+ _desc = self._strip_empty(_desc)
+ if any(_desc):
+ _desc = self._fix_field_desc(_desc)
+ field = ':%s %s: ' % (field_role, _name)
+ lines.extend(self._format_block(field, _desc))
+ else:
+ lines.append(':%s %s:' % (field_role, _name))
+
+ if _type:
+ lines.append(':%s %s: %s' % (type_role, _name, _type))
+ return lines + ['']
+
def _format_field(self, _name, _type, _desc):
_desc = self._strip_empty(_desc)
has_desc = any(_desc)
@@ -354,9 +377,11 @@ class GoogleDocstring(UnicodeMixin):
field = ''
if has_desc:
- if self._is_list(_desc):
- return [field, ''] + _desc
- return [field + _desc[0]] + _desc[1:]
+ _desc = self._fix_field_desc(_desc)
+ if _desc[0]:
+ return [field + _desc[0]] + _desc[1:]
+ else:
+ return [field] + _desc
else:
return [field]
@@ -393,6 +418,12 @@ class GoogleDocstring(UnicodeMixin):
return i
return len(line)
+ def _get_initial_indent(self, lines):
+ for line in lines:
+ if line:
+ return self._get_indent(line)
+ return 0
+
def _get_min_indent(self, lines):
min_indent = None
for line in lines:
@@ -529,11 +560,10 @@ class GoogleDocstring(UnicodeMixin):
def _parse_keyword_arguments_section(self, section):
fields = self._consume_fields()
if self._config.napoleon_use_keyword:
- return self._generate_docutils_params(
+ return self._format_docutils_params(
fields,
field_role="keyword",
- type_role="kwtype"
- )
+ type_role="kwtype")
else:
return self._format_fields('Keyword Arguments', fields)
@@ -560,26 +590,10 @@ class GoogleDocstring(UnicodeMixin):
def _parse_parameters_section(self, section):
fields = self._consume_fields()
if self._config.napoleon_use_param:
- return self._generate_docutils_params(fields)
+ return self._format_docutils_params(fields)
else:
return self._format_fields('Parameters', fields)
- def _generate_docutils_params(self, fields, field_role='param', type_role='type'):
- lines = []
- for _name, _type, _desc in fields:
- _desc = self._strip_empty(_desc)
- if any(_desc):
- if self._is_list(_desc):
- _desc = [''] + _desc
- field = ':%s %s: ' % (field_role, _name)
- lines.extend(self._format_block(field, _desc))
- else:
- lines.append(':%s %s:' % (field_role, _name))
-
- if _type:
- lines.append(':%s %s: %s' % (type_role, _name, _type))
- return lines + ['']
-
def _parse_raises_section(self, section):
fields = self._consume_fields(parse_type=False, prefer_type=True)
field_type = ':raises:'
@@ -678,11 +692,12 @@ class GoogleDocstring(UnicodeMixin):
if found_colon:
after_colon.append(source)
else:
- if (i % 2) == 0 and ":" in source:
+ m = _single_colon_regex.search(source)
+ if (i % 2) == 0 and m:
found_colon = True
- before, colon, after = source.partition(":")
- before_colon.append(before)
- after_colon.append(after)
+ colon = source[m.start(): m.end()]
+ before_colon.append(source[:m.start()])
+ after_colon.append(source[m.end():])
else:
before_colon.append(source)
@@ -715,36 +730,34 @@ class NumpyDocstring(GoogleDocstring):
Parameters
----------
- docstring : str or List[str]
+ docstring : :obj:`str` or :obj:`list` of :obj:`str`
The docstring to parse, given either as a string or split into
individual lines.
- config : Optional[sphinx.ext.napoleon.Config or sphinx.config.Config]
+ config: :obj:`sphinx.ext.napoleon.Config` or :obj:`sphinx.config.Config`
The configuration settings to use. If not given, defaults to the
config object on `app`; or if `app` is not given defaults to the
- a new `sphinx.ext.napoleon.Config` object.
+ a new :class:`sphinx.ext.napoleon.Config` object.
- See Also
- --------
- :class:`sphinx.ext.napoleon.Config`
Other Parameters
----------------
- app : Optional[sphinx.application.Sphinx]
+ app : :class:`sphinx.application.Sphinx`, optional
Application object representing the Sphinx process.
- what : Optional[str]
+ what : :obj:`str`, optional
A string specifying the type of the object to which the docstring
belongs. Valid values: "module", "class", "exception", "function",
"method", "attribute".
- name : Optional[str]
+ name : :obj:`str`, optional
The fully qualified name of the object.
obj : module, class, exception, function, method, or attribute
The object to which the docstring belongs.
- options : Optional[sphinx.ext.autodoc.Options]
+ options : :class:`sphinx.ext.autodoc.Options`, optional
The options given to the directive: an object with attributes
inherited_members, undoc_members, show_inheritance and noindex that
are True if the flag option of same name was given to the auto
directive.
+
Example
-------
>>> from sphinx.ext.napoleon import Config
@@ -801,7 +814,7 @@ class NumpyDocstring(GoogleDocstring):
Returns
-------
- List[str]
+ list(str)
The lines of the docstring in a list.
"""
diff --git a/sphinx/ext/todo.py b/sphinx/ext/todo.py
index a853ec93c..f3b526ce6 100644
--- a/sphinx/ext/todo.py
+++ b/sphinx/ext/todo.py
@@ -70,6 +70,8 @@ def process_todos(app, doctree):
if not hasattr(env, 'todo_all_todos'):
env.todo_all_todos = []
for node in doctree.traverse(todo_node):
+ app.emit('todo-defined', node)
+
try:
targetnode = node.parent[node.parent.index(node) - 1]
if not isinstance(targetnode, nodes.target):
@@ -86,6 +88,9 @@ def process_todos(app, doctree):
'target': targetnode,
})
+ if env.config.todo_emit_warnings:
+ env.warn_node("TODO entry found: %s" % node[1].astext(), node)
+
class TodoList(Directive):
"""
@@ -187,8 +192,10 @@ def depart_todo_node(self, node):
def setup(app):
+ app.add_event('todo-defined')
app.add_config_value('todo_include_todos', False, 'html')
app.add_config_value('todo_link_only', False, 'html')
+ app.add_config_value('todo_emit_warnings', False, 'html')
app.add_node(todolist)
app.add_node(todo_node,
diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py
index 89e7a9965..276a137d5 100644
--- a/sphinx/ext/viewcode.py
+++ b/sphinx/ext/viewcode.py
@@ -46,6 +46,10 @@ def doctree_read(app, doctree):
env = app.builder.env
if not hasattr(env, '_viewcode_modules'):
env._viewcode_modules = {}
+ if app.builder.name == "singlehtml":
+ return
+ if app.builder.name.startswith("epub") and not env.config.viewcode_enable_epub:
+ return
def has_tag(modname, fullname, docname, refname):
entry = env._viewcode_modules.get(modname, None)
@@ -139,8 +143,8 @@ def collect_pages(app):
# construct a page name for the highlighted source
pagename = '_modules/' + modname.replace('.', '/')
# highlight the source using the builder's highlighter
- if env.config.highlight_language == 'python3':
- lexer = 'python3'
+ if env.config.highlight_language in ('python3', 'default'):
+ lexer = env.config.highlight_language
else:
lexer = 'python'
highlighted = highlighter.highlight_block(code, lexer, linenos=False)
@@ -215,6 +219,7 @@ def collect_pages(app):
def setup(app):
app.add_config_value('viewcode_import', True, False)
+ app.add_config_value('viewcode_enable_epub', False, False)
app.connect('doctree-read', doctree_read)
app.connect('env-merge-info', env_merge_info)
app.connect('html-collect-pages', collect_pages)
diff --git a/sphinx/io.py b/sphinx/io.py
index 8d9970e80..36ac7bf98 100644
--- a/sphinx/io.py
+++ b/sphinx/io.py
@@ -15,7 +15,7 @@ from six import string_types, text_type
from sphinx.transforms import ApplySourceWorkaround, ExtraTranslatableNodes, Locale, \
CitationReferences, DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, \
- AutoNumbering, SortIds, RemoveTranslatableInline
+ AutoNumbering, AutoIndexUpgrader, SortIds, RemoveTranslatableInline
from sphinx.util import import_object, split_docinfo
@@ -59,7 +59,7 @@ class SphinxStandaloneReader(SphinxBaseReader):
"""
transforms = [ApplySourceWorkaround, ExtraTranslatableNodes, Locale, CitationReferences,
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks,
- AutoNumbering, SortIds, RemoveTranslatableInline]
+ AutoNumbering, AutoIndexUpgrader, SortIds, RemoveTranslatableInline]
class SphinxI18nReader(SphinxBaseReader):
@@ -112,10 +112,9 @@ class SphinxFileInput(FileInput):
return data.decode(self.encoding, 'sphinx') # py2: decoding
def read(self):
- def get_parser_type(docname):
- path = self.env.doc2path(docname)
+ def get_parser_type(source_path):
for suffix in self.env.config.source_parsers:
- if path.endswith(suffix):
+ if source_path.endswith(suffix):
parser_class = self.env.config.source_parsers[suffix]
if isinstance(parser_class, string_types):
parser_class = import_object(parser_class, 'source parser')
@@ -129,7 +128,7 @@ class SphinxFileInput(FileInput):
self.app.emit('source-read', self.env.docname, arg)
data = arg[0]
docinfo, data = split_docinfo(data)
- if 'restructuredtext' in get_parser_type(self.env.docname):
+ if 'restructuredtext' in get_parser_type(self.source_path):
if self.env.config.rst_epilog:
data = data + '\n' + self.env.config.rst_epilog + '\n'
if self.env.config.rst_prolog:
diff --git a/sphinx/make_mode.py b/sphinx/make_mode.py
index 9a17895bd..3bc8fa2a0 100644
--- a/sphinx/make_mode.py
+++ b/sphinx/make_mode.py
@@ -18,13 +18,12 @@ from __future__ import print_function
import os
import sys
-import shutil
from os import path
from subprocess import call
import sphinx
from sphinx.util.console import bold, blue
-from sphinx.util.osutil import cd
+from sphinx.util.osutil import cd, rmtree
proj_name = os.getenv('SPHINXPROJ', '<project>')
@@ -42,8 +41,6 @@ BUILDERS = [
("", "latex", "to make LaTeX files, you can set PAPER=a4 or PAPER=letter"),
("posix", "latexpdf", "to make LaTeX files and run them through pdflatex"),
("posix", "latexpdfja", "to make LaTeX files and run them through platex/dvipdfmx"),
- ("posix", "lualatexpdf", "to make LaTeX files and run them through lualatex"),
- ("posix", "xelatexpdf", "to make LaTeX files and run them through xelatex"),
("", "text", "to make text files"),
("", "man", "to make manual pages"),
("", "texinfo", "to make Texinfo files"),
@@ -77,7 +74,7 @@ class Make(object):
return 1
print("Removing everything under %r..." % self.builddir)
for item in os.listdir(self.builddir):
- shutil.rmtree(self.builddir_join(item))
+ rmtree(self.builddir_join(item))
def build_help(self):
print(bold("Sphinx v%s" % sphinx.__display_version__))
@@ -173,18 +170,6 @@ class Make(object):
with cd(self.builddir_join('latex')):
os.system('make all-pdf-ja')
- def build_lualatexpdf(self):
- if self.run_generic_build('latex') > 0:
- return 1
- with cd(self.builddir_join('latex')):
- os.system('make PDFLATEX=lualatex all-pdf')
-
- def build_xelatexpdf(self):
- if self.run_generic_build('latex') > 0:
- return 1
- with cd(self.builddir_join('latex')):
- os.system('make PDFLATEX=xelatex all-pdf')
-
def build_text(self):
if self.run_generic_build('text') > 0:
return 1
diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py
index 1fd2bd626..326da03db 100644
--- a/sphinx/quickstart.py
+++ b/sphinx/quickstart.py
@@ -34,10 +34,11 @@ from six.moves import input
from six.moves.urllib.parse import quote as urlquote
from docutils.utils import column_width
-from sphinx import __display_version__
+from sphinx import __display_version__, package_dir
from sphinx.util.osutil import make_filename
from sphinx.util.console import purple, bold, red, turquoise, \
nocolor, color_terminal
+from sphinx.util.template import SphinxRenderer
from sphinx.util import texescape
TERM_ENCODING = getattr(sys.stdin, 'encoding', None)
@@ -65,1057 +66,6 @@ EXTENSIONS = ('autodoc', 'doctest', 'intersphinx', 'todo', 'coverage',
PROMPT_PREFIX = '> '
-if PY3:
- # prevents that the file is checked for being written in Python 2.x syntax
- QUICKSTART_CONF = u'#!/usr/bin/env python3\n'
-else:
- QUICKSTART_CONF = u''
-
-QUICKSTART_CONF += u'''\
-# -*- coding: utf-8 -*-
-#
-# %(project)s documentation build configuration file, created by
-# sphinx-quickstart on %(now)s.
-#
-# This file is execfile()d with the current directory set to its
-# containing dir.
-#
-# Note that not all possible configuration values are present in this
-# autogenerated file.
-#
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#
-# import os
-# import sys
-# sys.path.insert(0, os.path.abspath('.'))
-
-# -- General configuration ------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#
-# needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be
-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
-# ones.
-extensions = [%(extensions)s]
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['%(dot)stemplates']
-
-# The suffix(es) of source filenames.
-# You can specify multiple suffix as a list of string:
-#
-# source_suffix = ['.rst', '.md']
-source_suffix = '%(suffix)s'
-
-# The encoding of source files.
-#
-# source_encoding = 'utf-8-sig'
-
-# The master toctree document.
-master_doc = '%(master_str)s'
-
-# General information about the project.
-project = u'%(project_str)s'
-copyright = u'%(copyright_str)s'
-author = u'%(author_str)s'
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# The short X.Y version.
-version = u'%(version_str)s'
-# The full version, including alpha/beta/rc tags.
-release = u'%(release_str)s'
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#
-# This is also used if you do content translation via gettext catalogs.
-# Usually you set "language" from the command line for these cases.
-language = %(language)r
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#
-# today = ''
-#
-# Else, today_fmt is used as the format for a strftime call.
-#
-# today_fmt = '%%B %%d, %%Y'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-# This patterns also effect to html_static_path and html_extra_path
-exclude_patterns = [%(exclude_patterns)s]
-
-# The reST default role (used for this markup: `text`) to use for all
-# documents.
-#
-# default_role = None
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#
-# add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#
-# add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#
-# show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-# A list of ignored prefixes for module index sorting.
-# modindex_common_prefix = []
-
-# If true, keep warnings as "system message" paragraphs in the built documents.
-# keep_warnings = False
-
-# If true, `todo` and `todoList` produce output, else they produce nothing.
-todo_include_todos = %(ext_todo)s
-
-
-# -- Options for HTML output ----------------------------------------------
-
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-#
-html_theme = 'alabaster'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-#
-# html_theme_options = {}
-
-# Add any paths that contain custom themes here, relative to this directory.
-# html_theme_path = []
-
-# The name for this set of Sphinx documents.
-# "<project> v<release> documentation" by default.
-#
-# html_title = u'%(project_str)s v%(release_str)s'
-
-# A shorter title for the navigation bar. Default is the same as html_title.
-#
-# html_short_title = None
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-#
-# html_logo = None
-
-# The name of an image file (relative to this directory) to use as a favicon of
-# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-#
-# html_favicon = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['%(dot)sstatic']
-
-# Add any extra paths that contain custom files (such as robots.txt or
-# .htaccess) here, relative to this directory. These files are copied
-# directly to the root of the documentation.
-#
-# html_extra_path = []
-
-# If not None, a 'Last updated on:' timestamp is inserted at every page
-# bottom, using the given strftime format.
-# The empty string is equivalent to '%%b %%d, %%Y'.
-#
-# html_last_updated_fmt = None
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#
-# html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-#
-# html_sidebars = {}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#
-# html_additional_pages = {}
-
-# If false, no module index is generated.
-#
-# html_domain_indices = True
-
-# If false, no index is generated.
-#
-# html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-#
-# html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-#
-# html_show_sourcelink = True
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#
-# html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#
-# html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it. The value of this option must be the
-# base URL from which the finished HTML is served.
-#
-# html_use_opensearch = ''
-
-# This is the file name suffix for HTML files (e.g. ".xhtml").
-# html_file_suffix = None
-
-# Language to be used for generating the HTML full-text search index.
-# Sphinx supports the following languages:
-# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
-# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
-#
-# html_search_language = 'en'
-
-# A dictionary with options for the search language support, empty by default.
-# 'ja' uses this config value.
-# 'zh' user can custom change `jieba` dictionary path.
-#
-# html_search_options = {'type': 'default'}
-
-# The name of a javascript file (relative to the configuration directory) that
-# implements a search results scorer. If empty, the default will be used.
-#
-# html_search_scorer = 'scorer.js'
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = '%(project_fn)sdoc'
-
-# -- Options for LaTeX output ---------------------------------------------
-
-latex_elements = {
- # The paper size ('letterpaper' or 'a4paper').
- #
- # 'papersize': 'letterpaper',
-
- # The font size ('10pt', '11pt' or '12pt').
- #
- # 'pointsize': '10pt',
-
- # Additional stuff for the LaTeX preamble.
- #
- # 'preamble': '',
-
- # Latex figure (float) alignment
- #
- # 'figure_align': 'htbp',
-}
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title,
-# author, documentclass [howto, manual, or own class]).
-latex_documents = [
- (master_doc, '%(project_fn)s.tex', u'%(project_doc_texescaped_str)s',
- u'%(author_texescaped_str)s', 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#
-# latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#
-# latex_use_parts = False
-
-# If true, show page references after internal links.
-#
-# latex_show_pagerefs = False
-
-# If true, show URL addresses after external links.
-#
-# latex_show_urls = False
-
-# Documents to append as an appendix to all manuals.
-#
-# latex_appendices = []
-
-# If false, no module index is generated.
-#
-# latex_domain_indices = True
-
-
-# -- Options for manual page output ---------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
- (master_doc, '%(project_manpage)s', u'%(project_doc_str)s',
- [author], 1)
-]
-
-# If true, show URL addresses after external links.
-#
-# man_show_urls = False
-
-
-# -- Options for Texinfo output -------------------------------------------
-
-# Grouping the document tree into Texinfo files. List of tuples
-# (source start file, target name, title, author,
-# dir menu entry, description, category)
-texinfo_documents = [
- (master_doc, '%(project_fn)s', u'%(project_doc_str)s',
- author, '%(project_fn)s', 'One line description of project.',
- 'Miscellaneous'),
-]
-
-# Documents to append as an appendix to all manuals.
-#
-# texinfo_appendices = []
-
-# If false, no module index is generated.
-#
-# texinfo_domain_indices = True
-
-# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#
-# texinfo_show_urls = 'footnote'
-
-# If true, do not generate a @detailmenu in the "Top" node's menu.
-#
-# texinfo_no_detailmenu = False
-'''
-
-EPUB_CONFIG = u'''
-
-# -- Options for Epub output ----------------------------------------------
-
-# Bibliographic Dublin Core info.
-epub_title = project
-epub_author = author
-epub_publisher = author
-epub_copyright = copyright
-
-# The basename for the epub file. It defaults to the project name.
-# epub_basename = project
-
-# The HTML theme for the epub output. Since the default themes are not
-# optimized for small screen space, using the same theme for HTML and epub
-# output is usually not wise. This defaults to 'epub', a theme designed to save
-# visual space.
-#
-# epub_theme = 'epub'
-
-# The language of the text. It defaults to the language option
-# or 'en' if the language is not set.
-#
-# epub_language = ''
-
-# The scheme of the identifier. Typical schemes are ISBN or URL.
-# epub_scheme = ''
-
-# The unique identifier of the text. This can be a ISBN number
-# or the project homepage.
-#
-# epub_identifier = ''
-
-# A unique identification for the text.
-#
-# epub_uid = ''
-
-# A tuple containing the cover image and cover page html template filenames.
-#
-# epub_cover = ()
-
-# A sequence of (type, uri, title) tuples for the guide element of content.opf.
-#
-# epub_guide = ()
-
-# HTML files that should be inserted before the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#
-# epub_pre_files = []
-
-# HTML files that should be inserted after the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#
-# epub_post_files = []
-
-# A list of files that should not be packed into the epub file.
-epub_exclude_files = ['search.html']
-
-# The depth of the table of contents in toc.ncx.
-#
-# epub_tocdepth = 3
-
-# Allow duplicate toc entries.
-#
-# epub_tocdup = True
-
-# Choose between 'default' and 'includehidden'.
-#
-# epub_tocscope = 'default'
-
-# Fix unsupported image types using the Pillow.
-#
-# epub_fix_images = False
-
-# Scale large images.
-#
-# epub_max_image_width = 0
-
-# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#
-# epub_show_urls = 'inline'
-
-# If false, no index is generated.
-#
-# epub_use_index = True
-'''
-
-INTERSPHINX_CONFIG = u'''
-
-# Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'https://docs.python.org/': None}
-'''
-
-MASTER_FILE = u'''\
-.. %(project)s documentation master file, created by
- sphinx-quickstart on %(now)s.
- You can adapt this file completely to your liking, but it should at least
- contain the root `toctree` directive.
-
-Welcome to %(project)s's documentation!
-===========%(project_underline)s=================
-
-Contents:
-
-.. toctree::
- :maxdepth: %(mastertocmaxdepth)s
-
-%(mastertoctree)s
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
-
-'''
-
-MAKEFILE = u'''\
-# Makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS =
-SPHINXBUILD = sphinx-build
-PAPER =
-BUILDDIR = %(rbuilddir)s
-
-# Internal variables.
-PAPEROPT_a4 = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) \
-$(SPHINXOPTS) %(rsrcdir)s
-# the i18n builder cannot share the environment and doctrees with the others
-I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) %(rsrcdir)s
-
-.PHONY: help
-help:
-\t@echo "Please use \\`make <target>' where <target> is one of"
-\t@echo " html to make standalone HTML files"
-\t@echo " dirhtml to make HTML files named index.html in directories"
-\t@echo " singlehtml to make a single large HTML file"
-\t@echo " pickle to make pickle files"
-\t@echo " json to make JSON files"
-\t@echo " htmlhelp to make HTML files and a HTML help project"
-\t@echo " qthelp to make HTML files and a qthelp project"
-\t@echo " applehelp to make an Apple Help Book"
-\t@echo " devhelp to make HTML files and a Devhelp project"
-\t@echo " epub to make an epub"
-\t@echo " epub3 to make an epub3"
-\t@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
-\t@echo " latexpdf to make LaTeX files and run them through pdflatex"
-\t@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
-\t@echo " lualatexpdf to make LaTeX files and run them through pdflatex"
-\t@echo " xelatexpdf to make LaTeX files and run them through pdflatex"
-\t@echo " text to make text files"
-\t@echo " man to make manual pages"
-\t@echo " texinfo to make Texinfo files"
-\t@echo " info to make Texinfo files and run them through makeinfo"
-\t@echo " gettext to make PO message catalogs"
-\t@echo " changes to make an overview of all changed/added/deprecated items"
-\t@echo " xml to make Docutils-native XML files"
-\t@echo " pseudoxml to make pseudoxml-XML files for display purposes"
-\t@echo " linkcheck to check all external links for integrity"
-\t@echo " doctest to run all doctests embedded in the documentation \
-(if enabled)"
-\t@echo " coverage to run coverage check of the documentation (if enabled)"
-\t@echo " dummy to check syntax errors of document sources"
-
-.PHONY: clean
-clean:
-\trm -rf $(BUILDDIR)/*
-
-.PHONY: html
-html:
-\t$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
-\t@echo
-\t@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
-.PHONY: dirhtml
-dirhtml:
-\t$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
-\t@echo
-\t@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-
-.PHONY: singlehtml
-singlehtml:
-\t$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
-\t@echo
-\t@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-
-.PHONY: pickle
-pickle:
-\t$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
-\t@echo
-\t@echo "Build finished; now you can process the pickle files."
-
-.PHONY: json
-json:
-\t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
-\t@echo
-\t@echo "Build finished; now you can process the JSON files."
-
-.PHONY: htmlhelp
-htmlhelp:
-\t$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
-\t@echo
-\t@echo "Build finished; now you can run HTML Help Workshop with the" \\
-\t ".hhp project file in $(BUILDDIR)/htmlhelp."
-
-.PHONY: qthelp
-qthelp:
-\t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
-\t@echo
-\t@echo "Build finished; now you can run "qcollectiongenerator" with the" \\
-\t ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
-\t@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/%(project_fn)s.qhcp"
-\t@echo "To view the help file:"
-\t@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/%(project_fn)s.qhc"
-
-.PHONY: applehelp
-applehelp:
-\t$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
-\t@echo
-\t@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
-\t@echo "N.B. You won't be able to view it unless you put it in" \\
-\t "~/Library/Documentation/Help or install it in your application" \\
-\t "bundle."
-
-.PHONY: devhelp
-devhelp:
-\t$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
-\t@echo
-\t@echo "Build finished."
-\t@echo "To view the help file:"
-\t@echo "# mkdir -p $$HOME/.local/share/devhelp/%(project_fn)s"
-\t@echo "# ln -s $(BUILDDIR)/devhelp\
- $$HOME/.local/share/devhelp/%(project_fn)s"
-\t@echo "# devhelp"
-
-.PHONY: epub
-epub:
-\t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
-\t@echo
-\t@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-
-.PHONY: epub3
-epub3:
-\t$(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
-\t@echo
-\t@echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
-
-.PHONY: latex
-latex:
-\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
-\t@echo
-\t@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
-\t@echo "Run \\`make' in that directory to run these through (pdf)latex" \\
-\t "(use \\`make latexpdf' here to do that automatically)."
-
-.PHONY: latexpdf
-latexpdf:
-\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
-\t@echo "Running LaTeX files through pdflatex..."
-\t$(MAKE) -C $(BUILDDIR)/latex all-pdf
-\t@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-.PHONY: latexpdfja
-latexpdfja:
-\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
-\t@echo "Running LaTeX files through platex and dvipdfmx..."
-\t$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
-\t@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-.PHONY: lualatexpdf
-lualatexpdf:
-\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
-\t@echo "Running LaTeX files through lualatex..."
-\t$(MAKE) PDFLATEX=lualatex -C $(BUILDDIR)/latex all-pdf
-\t@echo "lualatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-.PHONY: xelatexpdf
-xelatexpdf:
-\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
-\t@echo "Running LaTeX files through xelatex..."
-\t$(MAKE) PDFLATEX=xelatex -C $(BUILDDIR)/latex all-pdf
-\t@echo "xelatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-.PHONY: text
-text:
-\t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
-\t@echo
-\t@echo "Build finished. The text files are in $(BUILDDIR)/text."
-
-.PHONY: man
-man:
-\t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
-\t@echo
-\t@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
-
-.PHONY: texinfo
-texinfo:
-\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
-\t@echo
-\t@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
-\t@echo "Run \\`make' in that directory to run these through makeinfo" \\
-\t "(use \\`make info' here to do that automatically)."
-
-.PHONY: info
-info:
-\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
-\t@echo "Running Texinfo files through makeinfo..."
-\tmake -C $(BUILDDIR)/texinfo info
-\t@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
-
-.PHONY: gettext
-gettext:
-\t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
-\t@echo
-\t@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
-
-.PHONY: changes
-changes:
-\t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
-\t@echo
-\t@echo "The overview file is in $(BUILDDIR)/changes."
-
-.PHONY: linkcheck
-linkcheck:
-\t$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
-\t@echo
-\t@echo "Link check complete; look for any errors in the above output " \\
-\t "or in $(BUILDDIR)/linkcheck/output.txt."
-
-.PHONY: doctest
-doctest:
-\t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
-\t@echo "Testing of doctests in the sources finished, look at the " \\
-\t "results in $(BUILDDIR)/doctest/output.txt."
-
-.PHONY: coverage
-coverage:
-\t$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
-\t@echo "Testing of coverage in the sources finished, look at the " \\
-\t "results in $(BUILDDIR)/coverage/python.txt."
-
-.PHONY: xml
-xml:
-\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
-\t@echo
-\t@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
-
-.PHONY: pseudoxml
-pseudoxml:
-\t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
-\t@echo
-\t@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
-
-.PHONY: dummy
-dummy:
-\t$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
-\t@echo
-\t@echo "Build finished. Dummy builder generates no files."
-'''
-
-BATCHFILE = u'''\
-@ECHO OFF
-
-REM Command file for Sphinx documentation
-
-if "%%SPHINXBUILD%%" == "" (
-\tset SPHINXBUILD=sphinx-build
-)
-set BUILDDIR=%(rbuilddir)s
-set ALLSPHINXOPTS=-d %%BUILDDIR%%/doctrees %%SPHINXOPTS%% %(rsrcdir)s
-set I18NSPHINXOPTS=%%SPHINXOPTS%% %(rsrcdir)s
-if NOT "%%PAPER%%" == "" (
-\tset ALLSPHINXOPTS=-D latex_paper_size=%%PAPER%% %%ALLSPHINXOPTS%%
-\tset I18NSPHINXOPTS=-D latex_paper_size=%%PAPER%% %%I18NSPHINXOPTS%%
-)
-
-if "%%1" == "" goto help
-
-if "%%1" == "help" (
-\t:help
-\techo.Please use `make ^<target^>` where ^<target^> is one of
-\techo. html to make standalone HTML files
-\techo. dirhtml to make HTML files named index.html in directories
-\techo. singlehtml to make a single large HTML file
-\techo. pickle to make pickle files
-\techo. json to make JSON files
-\techo. htmlhelp to make HTML files and a HTML help project
-\techo. qthelp to make HTML files and a qthelp project
-\techo. devhelp to make HTML files and a Devhelp project
-\techo. epub to make an epub
-\techo. epub3 to make an epub3
-\techo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
-\techo. text to make text files
-\techo. man to make manual pages
-\techo. texinfo to make Texinfo files
-\techo. gettext to make PO message catalogs
-\techo. changes to make an overview over all changed/added/deprecated items
-\techo. xml to make Docutils-native XML files
-\techo. pseudoxml to make pseudoxml-XML files for display purposes
-\techo. linkcheck to check all external links for integrity
-\techo. doctest to run all doctests embedded in the documentation if enabled
-\techo. coverage to run coverage check of the documentation if enabled
-\techo. dummy to check syntax errors of document sources
-\tgoto end
-)
-
-if "%%1" == "clean" (
-\tfor /d %%%%i in (%%BUILDDIR%%\*) do rmdir /q /s %%%%i
-\tdel /q /s %%BUILDDIR%%\*
-\tgoto end
-)
-
-
-REM Check if sphinx-build is available and fallback to Python version if any
-%%SPHINXBUILD%% 1>NUL 2>NUL
-if errorlevel 9009 goto sphinx_python
-goto sphinx_ok
-
-:sphinx_python
-
-set SPHINXBUILD=python -m sphinx.__init__
-%%SPHINXBUILD%% 2> nul
-if errorlevel 9009 (
-\techo.
-\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx
-\techo.installed, then set the SPHINXBUILD environment variable to point
-\techo.to the full path of the 'sphinx-build' executable. Alternatively you
-\techo.may add the Sphinx directory to PATH.
-\techo.
-\techo.If you don't have Sphinx installed, grab it from
-\techo.http://sphinx-doc.org/
-\texit /b 1
-)
-
-:sphinx_ok
-
-
-if "%%1" == "html" (
-\t%%SPHINXBUILD%% -b html %%ALLSPHINXOPTS%% %%BUILDDIR%%/html
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished. The HTML pages are in %%BUILDDIR%%/html.
-\tgoto end
-)
-
-if "%%1" == "dirhtml" (
-\t%%SPHINXBUILD%% -b dirhtml %%ALLSPHINXOPTS%% %%BUILDDIR%%/dirhtml
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished. The HTML pages are in %%BUILDDIR%%/dirhtml.
-\tgoto end
-)
-
-if "%%1" == "singlehtml" (
-\t%%SPHINXBUILD%% -b singlehtml %%ALLSPHINXOPTS%% %%BUILDDIR%%/singlehtml
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished. The HTML pages are in %%BUILDDIR%%/singlehtml.
-\tgoto end
-)
-
-if "%%1" == "pickle" (
-\t%%SPHINXBUILD%% -b pickle %%ALLSPHINXOPTS%% %%BUILDDIR%%/pickle
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished; now you can process the pickle files.
-\tgoto end
-)
-
-if "%%1" == "json" (
-\t%%SPHINXBUILD%% -b json %%ALLSPHINXOPTS%% %%BUILDDIR%%/json
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished; now you can process the JSON files.
-\tgoto end
-)
-
-if "%%1" == "htmlhelp" (
-\t%%SPHINXBUILD%% -b htmlhelp %%ALLSPHINXOPTS%% %%BUILDDIR%%/htmlhelp
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished; now you can run HTML Help Workshop with the ^
-.hhp project file in %%BUILDDIR%%/htmlhelp.
-\tgoto end
-)
-
-if "%%1" == "qthelp" (
-\t%%SPHINXBUILD%% -b qthelp %%ALLSPHINXOPTS%% %%BUILDDIR%%/qthelp
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished; now you can run "qcollectiongenerator" with the ^
-.qhcp project file in %%BUILDDIR%%/qthelp, like this:
-\techo.^> qcollectiongenerator %%BUILDDIR%%\\qthelp\\%(project_fn)s.qhcp
-\techo.To view the help file:
-\techo.^> assistant -collectionFile %%BUILDDIR%%\\qthelp\\%(project_fn)s.ghc
-\tgoto end
-)
-
-if "%%1" == "devhelp" (
-\t%%SPHINXBUILD%% -b devhelp %%ALLSPHINXOPTS%% %%BUILDDIR%%/devhelp
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished.
-\tgoto end
-)
-
-if "%%1" == "epub" (
-\t%%SPHINXBUILD%% -b epub %%ALLSPHINXOPTS%% %%BUILDDIR%%/epub
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished. The epub file is in %%BUILDDIR%%/epub.
-\tgoto end
-)
-
-if "%%1" == "epub3" (
-\t%%SPHINXBUILD%% -b epub3 %%ALLSPHINXOPTS%% %%BUILDDIR%%/epub3
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished. The epub3 file is in %%BUILDDIR%%/epub3.
-\tgoto end
-)
-
-if "%%1" == "latex" (
-\t%%SPHINXBUILD%% -b latex %%ALLSPHINXOPTS%% %%BUILDDIR%%/latex
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished; the LaTeX files are in %%BUILDDIR%%/latex.
-\tgoto end
-)
-
-if "%%1" == "latexpdf" (
-\t%%SPHINXBUILD%% -b latex %%ALLSPHINXOPTS%% %%BUILDDIR%%/latex
-\tcd %%BUILDDIR%%/latex
-\tmake all-pdf
-\tcd %%~dp0
-\techo.
-\techo.Build finished; the PDF files are in %%BUILDDIR%%/latex.
-\tgoto end
-)
-
-if "%%1" == "latexpdfja" (
-\t%%SPHINXBUILD%% -b latex %%ALLSPHINXOPTS%% %%BUILDDIR%%/latex
-\tcd %%BUILDDIR%%/latex
-\tmake all-pdf-ja
-\tcd %%~dp0
-\techo.
-\techo.Build finished; the PDF files are in %%BUILDDIR%%/latex.
-\tgoto end
-)
-
-if "%%1" == "text" (
-\t%%SPHINXBUILD%% -b text %%ALLSPHINXOPTS%% %%BUILDDIR%%/text
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished. The text files are in %%BUILDDIR%%/text.
-\tgoto end
-)
-
-if "%%1" == "man" (
-\t%%SPHINXBUILD%% -b man %%ALLSPHINXOPTS%% %%BUILDDIR%%/man
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished. The manual pages are in %%BUILDDIR%%/man.
-\tgoto end
-)
-
-if "%%1" == "texinfo" (
-\t%%SPHINXBUILD%% -b texinfo %%ALLSPHINXOPTS%% %%BUILDDIR%%/texinfo
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished. The Texinfo files are in %%BUILDDIR%%/texinfo.
-\tgoto end
-)
-
-if "%%1" == "gettext" (
-\t%%SPHINXBUILD%% -b gettext %%I18NSPHINXOPTS%% %%BUILDDIR%%/locale
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished. The message catalogs are in %%BUILDDIR%%/locale.
-\tgoto end
-)
-
-if "%%1" == "changes" (
-\t%%SPHINXBUILD%% -b changes %%ALLSPHINXOPTS%% %%BUILDDIR%%/changes
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.The overview file is in %%BUILDDIR%%/changes.
-\tgoto end
-)
-
-if "%%1" == "linkcheck" (
-\t%%SPHINXBUILD%% -b linkcheck %%ALLSPHINXOPTS%% %%BUILDDIR%%/linkcheck
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Link check complete; look for any errors in the above output ^
-or in %%BUILDDIR%%/linkcheck/output.txt.
-\tgoto end
-)
-
-if "%%1" == "doctest" (
-\t%%SPHINXBUILD%% -b doctest %%ALLSPHINXOPTS%% %%BUILDDIR%%/doctest
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Testing of doctests in the sources finished, look at the ^
-results in %%BUILDDIR%%/doctest/output.txt.
-\tgoto end
-)
-
-if "%%1" == "coverage" (
-\t%%SPHINXBUILD%% -b coverage %%ALLSPHINXOPTS%% %%BUILDDIR%%/coverage
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Testing of coverage in the sources finished, look at the ^
-results in %%BUILDDIR%%/coverage/python.txt.
-\tgoto end
-)
-
-if "%%1" == "xml" (
-\t%%SPHINXBUILD%% -b xml %%ALLSPHINXOPTS%% %%BUILDDIR%%/xml
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished. The XML files are in %%BUILDDIR%%/xml.
-\tgoto end
-)
-
-if "%%1" == "pseudoxml" (
-\t%%SPHINXBUILD%% -b pseudoxml %%ALLSPHINXOPTS%% %%BUILDDIR%%/pseudoxml
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished. The pseudo-XML files are in %%BUILDDIR%%/pseudoxml.
-\tgoto end
-)
-
-if "%%1" == "dummy" (
-\t%%SPHINXBUILD%% -b dummy %%ALLSPHINXOPTS%% %%BUILDDIR%%/dummy
-\tif errorlevel 1 exit /b 1
-\techo.
-\techo.Build finished. Dummy builder generates no files.
-\tgoto end
-)
-
-:end
-'''
-
-# This will become the Makefile template for Sphinx 1.5.
-MAKEFILE_NEW = u'''\
-# Minimal makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS =
-SPHINXBUILD = sphinx-build
-SPHINXPROJ = %(project_fn)s
-SOURCEDIR = %(rsrcdir)s
-BUILDDIR = %(rbuilddir)s
-
-# Has to be explicit, otherwise we don't get "make" without targets right.
-help:
-\t@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
-
-# You can add custom targets here.
-
-# Catch-all target: route all unknown targets to Sphinx using the new
-# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
-%%:
-\t@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
-'''
-
-# This will become the make.bat template for Sphinx 1.5.
-BATCHFILE_NEW = u'''\
-@ECHO OFF
-
-REM Command file for Sphinx documentation
-
-if "%%SPHINXBUILD%%" == "" (
-\tset SPHINXBUILD=sphinx-build
-)
-set SOURCEDIR=%(rsrcdir)s
-set BUILDDIR=%(rbuilddir)s
-set SPHINXPROJ=%(project_fn)s
-
-if "%%1" == "" goto help
-
-%%SPHINXBUILD%% >NUL 2>NUL
-if errorlevel 9009 (
-\techo.
-\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx
-\techo.installed, then set the SPHINXBUILD environment variable to point
-\techo.to the full path of the 'sphinx-build' executable. Alternatively you
-\techo.may add the Sphinx directory to PATH.
-\techo.
-\techo.If you don't have Sphinx installed, grab it from
-\techo.http://sphinx-doc.org/
-\texit /b 1
-)
-
-%%SPHINXBUILD%% -M %%1 %%SOURCEDIR%% %%BUILDDIR%% %%SPHINXOPTS%%
-goto end
-
-:help
-%%SPHINXBUILD%% -M help %%SOURCEDIR%% %%BUILDDIR%% %%SPHINXOPTS%%
-
-:end
-'''
-
def mkdir_p(dir):
if path.isdir(dir):
@@ -1134,6 +84,10 @@ def is_path(x):
return x
+def allow_empty(x):
+ return x
+
+
def nonempty(x):
if not x:
raise ValidationError("Please enter some text.")
@@ -1220,15 +174,12 @@ def do_prompt(d, key, text, default=None, validator=nonempty):
d[key] = x
-if PY3:
+def convert_python_source(source, rex=re.compile(r"[uU]('.*?')")):
# remove Unicode literal prefixes
- def _convert_python_source(source, rex=re.compile(r"[uU]('.*?')")):
+ if PY3:
return rex.sub('\\1', source)
-
- for f in ['QUICKSTART_CONF', 'EPUB_CONFIG', 'INTERSPHINX_CONFIG']:
- globals()[f] = _convert_python_source(globals()[f])
-
- del _convert_python_source
+ else:
+ return source
def ask_user(d):
@@ -1306,9 +257,9 @@ software. Each version can have multiple releases. For example, for
Python the version is something like 2.5 or 3.0, while the release is
something like 2.5.1 or 3.0a1. If you don't need this dual structure,
just set both to the same value.''')
- do_prompt(d, 'version', 'Project version')
+ do_prompt(d, 'version', 'Project version', '', allow_empty)
if 'release' not in d:
- do_prompt(d, 'release', 'Project release', d['version'])
+ do_prompt(d, 'release', 'Project release', d['version'], allow_empty)
if 'language' not in d:
print('''
@@ -1408,6 +359,7 @@ directly.''')
def generate(d, overwrite=True, silent=False):
"""Generate project based on values in *d*."""
+ template = SphinxRenderer()
texescape.init()
indent = ' ' * 4
@@ -1417,6 +369,7 @@ def generate(d, overwrite=True, silent=False):
if 'mastertocmaxdepth' not in d:
d['mastertocmaxdepth'] = 2
+ d['PY3'] = PY3
d['project_fn'] = make_filename(d['project'])
d['project_url'] = urlquote(d['project'].encode('idna'))
d['project_manpage'] = d['project_fn'].lower()
@@ -1472,34 +425,33 @@ def generate(d, overwrite=True, silent=False):
else:
print('File %s already exists, skipping.' % fpath)
- conf_text = QUICKSTART_CONF % d
- if d['epub']:
- conf_text += EPUB_CONFIG % d
- if d.get('ext_intersphinx'):
- conf_text += INTERSPHINX_CONFIG
+ with open(os.path.join(package_dir, 'templates', 'quickstart', 'conf.py_t')) as f:
+ conf_text = convert_python_source(f.read())
- write_file(path.join(srcdir, 'conf.py'), conf_text)
+ write_file(path.join(srcdir, 'conf.py'), template.render_string(conf_text, d))
masterfile = path.join(srcdir, d['master'] + d['suffix'])
- write_file(masterfile, MASTER_FILE % d)
+ write_file(masterfile, template.render('quickstart/master_doc.rst_t', d))
if d.get('make_mode') is True:
- makefile_template = MAKEFILE_NEW
- batchfile_template = BATCHFILE_NEW
+ makefile_template = 'quickstart/Makefile.new_t'
+ batchfile_template = 'quickstart/make.bat.new_t'
else:
- makefile_template = MAKEFILE
- batchfile_template = BATCHFILE
+ makefile_template = 'quickstart/Makefile_t'
+ batchfile_template = 'quickstart/make.bat_t'
if d['makefile'] is True:
d['rsrcdir'] = d['sep'] and 'source' or '.'
d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build'
# use binary mode, to avoid writing \r\n on Windows
- write_file(path.join(d['path'], 'Makefile'), makefile_template % d, u'\n')
+ write_file(path.join(d['path'], 'Makefile'),
+ template.render(makefile_template, d), u'\n')
if d['batchfile'] is True:
d['rsrcdir'] = d['sep'] and 'source' or '.'
d['rbuilddir'] = d['sep'] and 'build' or d['dot'] + 'build'
- write_file(path.join(d['path'], 'make.bat'), batchfile_template % d, u'\r\n')
+ write_file(path.join(d['path'], 'make.bat'),
+ template.render(batchfile_template, d), u'\r\n')
if silent:
return
@@ -1650,13 +602,14 @@ def main(argv=sys.argv):
try:
if 'quiet' in d:
- if not set(['project', 'author', 'version']).issubset(d):
- print('''"quiet" is specified, but any of "project", \
-"author" or "version" is not specified.''')
+ if not set(['project', 'author']).issubset(d):
+ print('''"quiet" is specified, but any of "project" or \
+"author" is not specified.''')
return
- if set(['quiet', 'project', 'author', 'version']).issubset(d):
+ if set(['quiet', 'project', 'author']).issubset(d):
# quiet mode with all required params satisfied, use default
+ d.setdefault('version', '')
d.setdefault('release', d['version'])
d2 = DEFAULT_VALUE.copy()
d2.update(dict(("ext_"+ext, False) for ext in EXTENSIONS))
diff --git a/sphinx/roles.py b/sphinx/roles.py
index a6583a6ea..6e8de3b4a 100644
--- a/sphinx/roles.py
+++ b/sphinx/roles.py
@@ -13,7 +13,6 @@ import re
from six import iteritems
from docutils import nodes, utils
-from docutils.parsers.rst import roles
from sphinx import addnodes
from sphinx.locale import _
@@ -36,11 +35,6 @@ generic_docroles = {
'regexp': nodes.literal,
}
-for rolename, nodeclass in iteritems(generic_docroles):
- generic = roles.GenericRole(rolename, nodeclass)
- role = roles.CustomRole(rolename, generic, {'classes': [rolename]})
- roles.register_local_role(rolename, role)
-
# -- generic cross-reference role ----------------------------------------------
@@ -344,5 +338,14 @@ specific_docroles = {
'index': index_role,
}
-for rolename, func in iteritems(specific_docroles):
- roles.register_local_role(rolename, func)
+
+def setup(app):
+ from docutils.parsers.rst import roles
+
+ for rolename, nodeclass in iteritems(generic_docroles):
+ generic = roles.GenericRole(rolename, nodeclass)
+ role = roles.CustomRole(rolename, generic, {'classes': [rolename]})
+ roles.register_local_role(rolename, role)
+
+ for rolename, func in iteritems(specific_docroles):
+ roles.register_local_role(rolename, func)
diff --git a/sphinx/search/__init__.py b/sphinx/search/__init__.py
index 8bbce360e..6e21b2f5f 100644
--- a/sphinx/search/__init__.py
+++ b/sphinx/search/__init__.py
@@ -226,11 +226,13 @@ class IndexBuilder(object):
def __init__(self, env, lang, options, scoring):
self.env = env
- # filename -> title
+ # docname -> title
self._titles = {}
- # stemmed word -> set(filenames)
+ # docname -> filename
+ self._filenames = {}
+ # stemmed word -> set(docname)
self._mapping = {}
- # stemmed words in titles -> set(filenames)
+ # stemmed words in titles -> set(docname)
self._title_mapping = {}
# word -> stemmed word
self._stem_cache = {}
@@ -338,15 +340,16 @@ class IndexBuilder(object):
def freeze(self):
"""Create a usable data structure for serializing."""
- filenames, titles = zip(*sorted(self._titles.items()))
- fn2index = dict((f, i) for (i, f) in enumerate(filenames))
+ docnames, titles = zip(*sorted(self._titles.items()))
+ filenames = [self._filenames.get(docname) for docname in docnames]
+ fn2index = dict((f, i) for (i, f) in enumerate(docnames))
terms, title_terms = self.get_terms(fn2index)
objects = self.get_objects(fn2index) # populates _objtypes
objtypes = dict((v, k[0] + ':' + k[1])
for (k, v) in iteritems(self._objtypes))
objnames = self._objnames
- return dict(filenames=filenames, titles=titles, terms=terms,
+ return dict(docnames=docnames, filenames=filenames, titles=titles, terms=terms,
objects=objects, objtypes=objtypes, objnames=objnames,
titleterms=title_terms, envversion=self.env.version)
@@ -365,9 +368,11 @@ class IndexBuilder(object):
for wordnames in itervalues(self._title_mapping):
wordnames.intersection_update(filenames)
- def feed(self, filename, title, doctree):
+ def feed(self, docname, filename, title, doctree):
"""Feed a doctree to the index."""
- self._titles[filename] = title
+ self._titles[docname] = title
+ self._filenames[docname] = filename
+
visitor = WordCollector(doctree, self.lang)
doctree.walk(visitor)
@@ -381,14 +386,19 @@ class IndexBuilder(object):
_filter = self.lang.word_filter
for word in visitor.found_title_words:
- word = stem(word)
- if _filter(word):
- self._title_mapping.setdefault(word, set()).add(filename)
+ stemmed_word = stem(word)
+ if _filter(stemmed_word):
+ self._title_mapping.setdefault(stemmed_word, set()).add(docname)
+ elif _filter(word): # stemmer must not remove words from search index
+ self._title_mapping.setdefault(word, set()).add(docname)
for word in visitor.found_words:
- word = stem(word)
- if word not in self._title_mapping and _filter(word):
- self._mapping.setdefault(word, set()).add(filename)
+ stemmed_word = stem(word)
+ # again, stemmer must not remove words from search index
+ if not _filter(stemmed_word) and _filter(word):
+ stemmed_word = word
+ if stemmed_word not in self._title_mapping and _filter(stemmed_word):
+ self._mapping.setdefault(stemmed_word, set()).add(docname)
def context_for_searchtool(self):
return dict(
diff --git a/tests/roots/test-html_extra_path/extra/.htaccess b/sphinx/search/test
index e69de29bb..e69de29bb 100644
--- a/tests/roots/test-html_extra_path/extra/.htaccess
+++ b/sphinx/search/test
diff --git a/sphinx/setup_command.py b/sphinx/setup_command.py
index 128c1415c..7df8bd6e8 100644
--- a/sphinx/setup_command.py
+++ b/sphinx/setup_command.py
@@ -15,6 +15,8 @@ from __future__ import print_function
import sys
import os
+import traceback
+
from distutils.cmd import Command
from distutils.errors import DistutilsOptionError, DistutilsExecError
@@ -71,6 +73,7 @@ class BuildDoc(Command):
('build-dir=', None, 'Build directory'),
('config-dir=', 'c', 'Location of the configuration directory'),
('builder=', 'b', 'The builder to use. Defaults to "html"'),
+ ('warning-is-error', 'W', 'Turn warning into errors'),
('project=', None, 'The documented project\'s name'),
('version=', None, 'The short X.Y version'),
('release=', None, 'The full version, including alpha/beta/rc tags'),
@@ -78,13 +81,17 @@ class BuildDoc(Command):
'replacement for |today|'),
('link-index', 'i', 'Link index.html to the master doc'),
('copyright', None, 'The copyright string'),
+ ('pdb', None, 'Start pdb on exception'),
]
- boolean_options = ['fresh-env', 'all-files', 'link-index']
+ boolean_options = ['fresh-env', 'all-files', 'warning-is-error',
+ 'link-index']
def initialize_options(self):
self.fresh_env = self.all_files = False
+ self.pdb = False
self.source_dir = self.build_dir = None
self.builder = 'html'
+ self.warning_is_error = False
self.project = ''
self.version = ''
self.release = ''
@@ -158,7 +165,8 @@ class BuildDoc(Command):
app = Sphinx(self.source_dir, self.config_dir,
self.builder_target_dir, self.doctree_dir,
self.builder, confoverrides, status_stream,
- freshenv=self.fresh_env)
+ freshenv=self.fresh_env,
+ warningiserror=self.warning_is_error)
try:
app.build(force_all=self.all_files)
@@ -166,13 +174,20 @@ class BuildDoc(Command):
raise DistutilsExecError(
'caused by %s builder.' % app.builder.name)
except Exception as err:
- from docutils.utils import SystemMessage
- if isinstance(err, SystemMessage):
- print(darkred('reST markup error:'), file=sys.stderr)
- print(err.args[0].encode('ascii', 'backslashreplace'),
+ if self.pdb:
+ import pdb
+ print(darkred('Exception occurred while building, starting debugger:'),
file=sys.stderr)
+ traceback.print_exc()
+ pdb.post_mortem(sys.exc_info()[2])
else:
- raise
+ from docutils.utils import SystemMessage
+ if isinstance(err, SystemMessage):
+ print(darkred('reST markup error:'), file=sys.stderr)
+ print(err.args[0].encode('ascii', 'backslashreplace'),
+ file=sys.stderr)
+ else:
+ raise
if self.link_index:
src = app.config.master_doc + app.builder.out_suffix
diff --git a/sphinx/templates/latex/content.tex_t b/sphinx/templates/latex/content.tex_t
new file mode 100644
index 000000000..cac910945
--- /dev/null
+++ b/sphinx/templates/latex/content.tex_t
@@ -0,0 +1,41 @@
+%% Generated by Sphinx.
+\def\sphinxdocclass{<%= docclass %>}
+\newif\ifsphinxKeepOldNames <%= keepoldnames %>
+\documentclass[<%= papersize %>,<%= pointsize %><%= classoptions %>]{<%= wrapperclass %>}
+\ifdefined\pdfpxdimen
+ \let\sphinxpxdimen\pdfpxdimen\else\newdimen\sphinxpxdimen
+\fi \sphinxpxdimen=<%= pxunit %>\relax
+<%= passoptionstopackages %>
+<%= inputenc %>
+<%= utf8extra %>
+<%= cmappkg %>
+<%= fontenc %>
+<%= amsmath %>
+<%= babel %>
+<%= fontpkg %>
+<%= fncychap %>
+<%= longtable %>
+\usepackage{sphinx}
+\usepackage{multirow}
+\usepackage{eqparbox}
+<%= usepackages %>
+<%= contentsname %>
+<%= numfig_format %>
+<%= pageautorefname %>
+<%= tocdepth %>
+<%= secnumdepth %>
+<%= preamble %>
+
+\title{<%= title %>}
+\date{<%= date %>}
+\release{<%= release %>}
+\author{<%= author %>}
+\newcommand{\sphinxlogo}{<%= logo %>}
+\renewcommand{\releasename}{<%= releasename %>}
+<%= makeindex %>
+<%= body %>
+<%= footer %>
+<%= indices %>
+\renewcommand{\indexname}{<%= indexname %>}
+<%= printindex %>
+\end{document}
diff --git a/sphinx/templates/quickstart/Makefile.new_t b/sphinx/templates/quickstart/Makefile.new_t
new file mode 100644
index 000000000..f160bc212
--- /dev/null
+++ b/sphinx/templates/quickstart/Makefile.new_t
@@ -0,0 +1,21 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+SPHINXPROJ = {{ project_fn }}
+SOURCEDIR = {{ rsrcdir }}
+BUILDDIR = {{ rbuilddir }}
+
+# Has to be explicit, otherwise we don't get "make" without targets right.
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+# You can add custom targets here.
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%:
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
diff --git a/sphinx/templates/quickstart/Makefile_t b/sphinx/templates/quickstart/Makefile_t
new file mode 100644
index 000000000..f86d2545a
--- /dev/null
+++ b/sphinx/templates/quickstart/Makefile_t
@@ -0,0 +1,242 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = {{ rbuilddir }}
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) {{ rsrcdir }}
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) {{ rsrcdir }}
+
+.PHONY: help
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " applehelp to make an Apple Help Book"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " epub3 to make an epub3"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+ @echo " lualatexpdf to make LaTeX files and run them through lualatex"
+ @echo " xelatexpdf to make LaTeX files and run them through xelatex"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " xml to make Docutils-native XML files"
+ @echo " pseudoxml to make pseudoxml-XML files for display purposes"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+ @echo " coverage to run coverage check of the documentation (if enabled)"
+ @echo " dummy to check syntax errors of document sources"
+
+.PHONY: clean
+clean:
+ rm -rf $(BUILDDIR)/*
+
+.PHONY: html
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+.PHONY: dirhtml
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+.PHONY: singlehtml
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+.PHONY: pickle
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+.PHONY: json
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+.PHONY: htmlhelp
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+.PHONY: qthelp
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/{{ project_fn }}.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/{{ project_fn }}.qhc"
+
+.PHONY: applehelp
+applehelp:
+ $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
+ @echo
+ @echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
+ @echo "N.B. You won't be able to view it unless you put it in" \
+ "~/Library/Documentation/Help or install it in your application" \
+ "bundle."
+
+.PHONY: devhelp
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/{{ project_fn }}"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/{{ project_fn }}"
+ @echo "# devhelp"
+
+.PHONY: epub
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+.PHONY: epub3
+epub3:
+ $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
+ @echo
+ @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
+
+.PHONY: latex
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+.PHONY: latexpdf
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+.PHONY: latexpdfja
+latexpdfja:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through platex and dvipdfmx..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+.PHONY: lualatexpdf
+lualatexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through lualatex..."
+ $(MAKE) PDFLATEX=lualatex -C $(BUILDDIR)/latex all-pdf
+ @echo "lualatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+.PHONY: xelatexpdf
+xelatexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through xelatex..."
+ $(MAKE) PDFLATEX=xelatex -C $(BUILDDIR)/latex all-pdf
+ @echo "xelatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+.PHONY: text
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+.PHONY: man
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+.PHONY: texinfo
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+.PHONY: info
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+.PHONY: gettext
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+.PHONY: changes
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+.PHONY: linkcheck
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+.PHONY: doctest
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
+
+.PHONY: coverage
+coverage:
+ $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
+ @echo "Testing of coverage in the sources finished, look at the " \
+ "results in $(BUILDDIR)/coverage/python.txt."
+
+.PHONY: xml
+xml:
+ $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+ @echo
+ @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+.PHONY: pseudoxml
+pseudoxml:
+ $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+ @echo
+ @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
+
+.PHONY: dummy
+dummy:
+ $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
+ @echo
+ @echo "Build finished. Dummy builder generates no files."
+
diff --git a/sphinx/templates/quickstart/conf.py_t b/sphinx/templates/quickstart/conf.py_t
new file mode 100644
index 000000000..5022bbdb5
--- /dev/null
+++ b/sphinx/templates/quickstart/conf.py_t
@@ -0,0 +1,433 @@
+{% if PY3 -%}
+#!/usr/bin/env python3
+{% endif -%}
+# -*- coding: utf-8 -*-
+#
+# {{ project }} documentation build configuration file, created by
+# sphinx-quickstart on {{ now }}.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [{{ extensions }}]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['{{ dot }}templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '{{ suffix }}'
+
+# The encoding of source files.
+#
+# source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = '{{ master_str }}'
+
+# General information about the project.
+project = u'{{ project_str }}'
+copyright = u'{{ copyright_str }}'
+author = u'{{ author_str }}'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = u'{{ version_str }}'
+# The full version, including alpha/beta/rc tags.
+release = u'{{ release_str }}'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = {{ language | repr }}
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#
+# today = ''
+#
+# Else, today_fmt is used as the format for a strftime call.
+#
+# today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This patterns also effect to html_static_path and html_extra_path
+exclude_patterns = [{{ exclude_patterns }}]
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#
+# default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#
+# add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#
+# add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#
+# show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+# modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+# keep_warnings = False
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = {{ ext_todo }}
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'alabaster'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#
+# html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+# html_theme_path = []
+
+# The name for this set of Sphinx documents.
+# "<project> v<release> documentation" by default.
+#
+# html_title = u'{{ project_str }} v{{ release_str }}'
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#
+# html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#
+# html_logo = None
+
+# The name of an image file (relative to this directory) to use as a favicon of
+# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#
+# html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['{{ dot }}static']
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#
+# html_extra_path = []
+
+# If not None, a 'Last updated on:' timestamp is inserted at every page
+# bottom, using the given strftime format.
+# The empty string is equivalent to '%b %d, %Y'.
+#
+# html_last_updated_fmt = None
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#
+# html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#
+# html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#
+# html_additional_pages = {}
+
+# If false, no module index is generated.
+#
+# html_domain_indices = True
+
+# If false, no index is generated.
+#
+# html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#
+# html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#
+# html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#
+# html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#
+# html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#
+# html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+# html_file_suffix = None
+
+# Language to be used for generating the HTML full-text search index.
+# Sphinx supports the following languages:
+# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
+# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
+#
+# html_search_language = 'en'
+
+# A dictionary with options for the search language support, empty by default.
+# 'ja' uses this config value.
+# 'zh' user can custom change `jieba` dictionary path.
+#
+# html_search_options = {'type': 'default'}
+
+# The name of a javascript file (relative to the configuration directory) that
+# implements a search results scorer. If empty, the default will be used.
+#
+# html_search_scorer = 'scorer.js'
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = '{{ project_fn }}doc'
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+ # The paper size ('letterpaper' or 'a4paper').
+ #
+ # 'papersize': 'letterpaper',
+
+ # The font size ('10pt', '11pt' or '12pt').
+ #
+ # 'pointsize': '10pt',
+
+ # Additional stuff for the LaTeX preamble.
+ #
+ # 'preamble': '',
+
+ # Latex figure (float) alignment
+ #
+ # 'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+latex_documents = [
+ (master_doc, '{{ project_fn }}.tex', u'{{ project_doc_texescaped_str }}',
+ u'{{ author_texescaped_str }}', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#
+# latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#
+# latex_use_parts = False
+
+# If true, show page references after internal links.
+#
+# latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#
+# latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#
+# latex_appendices = []
+
+# It false, will not define \strong, \code, \titleref, \crossref ... but only
+# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added
+# packages.
+#
+# latex_keep_old_macro_names = True
+
+# If false, no module index is generated.
+#
+# latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ (master_doc, '{{ project_manpage }}', u'{{ project_doc_str }}',
+ [author], 1)
+]
+
+# If true, show URL addresses after external links.
+#
+# man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ (master_doc, '{{ project_fn }}', u'{{ project_doc_str }}',
+ author, '{{ project_fn }}', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#
+# texinfo_appendices = []
+
+# If false, no module index is generated.
+#
+# texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#
+# texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#
+# texinfo_no_detailmenu = False
+
+{% if epub %}
+# -- Options for Epub output ----------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = project
+epub_author = author
+epub_publisher = author
+epub_copyright = copyright
+
+# The basename for the epub file. It defaults to the project name.
+# epub_basename = project
+
+# The HTML theme for the epub output. Since the default themes are not
+# optimized for small screen space, using the same theme for HTML and epub
+# output is usually not wise. This defaults to 'epub', a theme designed to save
+# visual space.
+#
+# epub_theme = 'epub'
+
+# The language of the text. It defaults to the language option
+# or 'en' if the language is not set.
+#
+# epub_language = ''
+
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+# epub_scheme = ''
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#
+# epub_identifier = ''
+
+# A unique identification for the text.
+#
+# epub_uid = ''
+
+# A tuple containing the cover image and cover page html template filenames.
+#
+# epub_cover = ()
+
+# A sequence of (type, uri, title) tuples for the guide element of content.opf.
+#
+# epub_guide = ()
+
+# HTML files that should be inserted before the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#
+# epub_pre_files = []
+
+# HTML files that should be inserted after the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#
+# epub_post_files = []
+
+# A list of files that should not be packed into the epub file.
+epub_exclude_files = ['search.html']
+
+# The depth of the table of contents in toc.ncx.
+#
+# epub_tocdepth = 3
+
+# Allow duplicate toc entries.
+#
+# epub_tocdup = True
+
+# Choose between 'default' and 'includehidden'.
+#
+# epub_tocscope = 'default'
+
+# Fix unsupported image types using the Pillow.
+#
+# epub_fix_images = False
+
+# Scale large images.
+#
+# epub_max_image_width = 0
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#
+# epub_show_urls = 'inline'
+
+# If false, no index is generated.
+#
+# epub_use_index = True
+{% endif %}
+
+{% if ext_intersphinx %}
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'https://docs.python.org/': None}
+{% endif %}
+
diff --git a/sphinx/templates/quickstart/make.bat.new_t b/sphinx/templates/quickstart/make.bat.new_t
new file mode 100644
index 000000000..4ed82305c
--- /dev/null
+++ b/sphinx/templates/quickstart/make.bat.new_t
@@ -0,0 +1,34 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR={{ rsrcdir }}
+set BUILDDIR={{ rbuilddir }}
+set SPHINXPROJ={{ project_fn }}
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+
+:end
+
diff --git a/sphinx/templates/quickstart/make.bat_t b/sphinx/templates/quickstart/make.bat_t
new file mode 100644
index 000000000..88a8fa9d9
--- /dev/null
+++ b/sphinx/templates/quickstart/make.bat_t
@@ -0,0 +1,282 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR={{ rbuilddir }}
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% {{ rsrcdir }}
+set I18NSPHINXOPTS=%SPHINXOPTS% {{ rsrcdir }}
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^<target^>` where ^<target^> is one of
+ echo. html to make standalone HTML files
+ echo. dirhtml to make HTML files named index.html in directories
+ echo. singlehtml to make a single large HTML file
+ echo. pickle to make pickle files
+ echo. json to make JSON files
+ echo. htmlhelp to make HTML files and a HTML help project
+ echo. qthelp to make HTML files and a qthelp project
+ echo. devhelp to make HTML files and a Devhelp project
+ echo. epub to make an epub
+ echo. epub3 to make an epub3
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+ echo. text to make text files
+ echo. man to make manual pages
+ echo. texinfo to make Texinfo files
+ echo. gettext to make PO message catalogs
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. xml to make Docutils-native XML files
+ echo. pseudoxml to make pseudoxml-XML files for display purposes
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ echo. coverage to run coverage check of the documentation if enabled
+ echo. dummy to check syntax errors of document sources
+ goto end
+)
+
+if "%1" == "clean" (
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+
+REM Check if sphinx-build is available and fallback to Python version if any
+%SPHINXBUILD% 1>NUL 2>NUL
+if errorlevel 9009 goto sphinx_python
+goto sphinx_ok
+
+:sphinx_python
+
+set SPHINXBUILD=python -m sphinx.__init__
+%SPHINXBUILD% 2> nul
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+:sphinx_ok
+
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\{{ project_fn }}.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\{{ project_fn }}.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "epub3" (
+ %SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub3 file is in %BUILDDIR%/epub3.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdf" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf
+ cd %~dp0
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdfja" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf-ja
+ cd %~dp0
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "texinfo" (
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+ goto end
+)
+
+if "%1" == "gettext" (
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+if "%1" == "coverage" (
+ %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of coverage in the sources finished, look at the ^
+results in %BUILDDIR%/coverage/python.txt.
+ goto end
+)
+
+if "%1" == "xml" (
+ %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The XML files are in %BUILDDIR%/xml.
+ goto end
+)
+
+if "%1" == "pseudoxml" (
+ %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
+ goto end
+)
+
+if "%1" == "dummy" (
+ %SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. Dummy builder generates no files.
+ goto end
+)
+
+:end
+
diff --git a/sphinx/templates/quickstart/master_doc.rst_t b/sphinx/templates/quickstart/master_doc.rst_t
new file mode 100644
index 000000000..f5ec13309
--- /dev/null
+++ b/sphinx/templates/quickstart/master_doc.rst_t
@@ -0,0 +1,22 @@
+.. {{ project }} documentation master file, created by
+ sphinx-quickstart on {{ now }}.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to {{ project }}'s documentation!
+==========={{ project_underline }}=================
+
+Contents:
+
+.. toctree::
+ :maxdepth: {{ mastertocmaxdepth }}
+
+{{ mastertoctree }}
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
diff --git a/sphinx/texinputs/Makefile b/sphinx/texinputs/Makefile_t
index d748006cc..ffec3662c 100644
--- a/sphinx/texinputs/Makefile
+++ b/sphinx/texinputs/Makefile_t
@@ -3,6 +3,7 @@
ALLDOCS = $(basename $(wildcard *.tex))
ALLPDF = $(addsuffix .pdf,$(ALLDOCS))
ALLDVI = $(addsuffix .dvi,$(ALLDOCS))
+ALLPS = $(addsuffix .ps,$(ALLDOCS))
# Prefix for archive names
ARCHIVEPRREFIX =
@@ -12,14 +13,18 @@ LATEXOPTS =
FMT = pdf
LATEX = latex
-PDFLATEX = pdflatex
+PDFLATEX = {{ latex_engine }}
MAKEINDEX = makeindex
+{% if latex_engine == 'platex' %}
+all: all-pdf-ja
+all-pdf: all-pdf-ja
+{% else %}
all: $(ALLPDF)
all-pdf: $(ALLPDF)
+{% endif -%}
all-dvi: $(ALLDVI)
-all-ps: all-dvi
- for f in *.dvi; do dvips $$f; done
+all-ps: $(ALLPS)
all-pdf-ja:
for f in *.pdf *.png *.gif *.jpg *.jpeg; do extractbb $$f; done
@@ -70,6 +75,9 @@ xz: tar
$(PDFLATEX) $(LATEXOPTS) '$<'
$(PDFLATEX) $(LATEXOPTS) '$<'
+%.ps: %.dvi
+ dvips '$<'
+
clean:
rm -f *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla *.ps *.tar *.tar.gz *.tar.bz2 *.tar.xz $(ALLPDF) $(ALLDVI)
diff --git a/sphinx/texinputs/needspace.sty b/sphinx/texinputs/needspace.sty
new file mode 100644
index 000000000..113d87216
--- /dev/null
+++ b/sphinx/texinputs/needspace.sty
@@ -0,0 +1,35 @@
+
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{needspace}[2010/09/12 v1.3d reserve vertical space]
+
+\newcommand{\needspace}[1]{%
+ \begingroup
+ \setlength{\dimen@}{#1}%
+ \vskip\z@\@plus\dimen@
+ \penalty -100\vskip\z@\@plus -\dimen@
+ \vskip\dimen@
+ \penalty 9999%
+ \vskip -\dimen@
+ \vskip\z@skip % hide the previous |\vskip| from |\addvspace|
+ \endgroup
+}
+
+\newcommand{\Needspace}{\@ifstar{\@sneedsp@}{\@needsp@}}
+
+\newcommand{\@sneedsp@}[1]{\par \penalty-100\begingroup
+ \setlength{\dimen@}{#1}%
+ \dimen@ii\pagegoal \advance\dimen@ii-\pagetotal
+ \ifdim \dimen@>\dimen@ii
+ \break
+ \fi\endgroup}
+
+\newcommand{\@needsp@}[1]{\par \penalty-100\begingroup
+ \setlength{\dimen@}{#1}%
+ \dimen@ii\pagegoal \advance\dimen@ii-\pagetotal
+ \ifdim \dimen@>\dimen@ii
+ \ifdim \dimen@ii>\z@
+ \vfil
+ \fi
+ \break
+ \fi\endgroup}
+
diff --git a/sphinx/texinputs/newfloat.sty b/sphinx/texinputs/newfloat.sty
deleted file mode 100644
index 47ac5e568..000000000
--- a/sphinx/texinputs/newfloat.sty
+++ /dev/null
@@ -1,737 +0,0 @@
-%%
-%% This is file `newfloat.sty',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% newfloat.dtx (with options: `package')
-%%
-%% Copyright (C) 1994-2016 Axel Sommerfeldt (axel.sommerfeldt@f-m.fm)
-%%
-%% http://sourceforge.net/projects/latex-caption/
-%%
-%% --------------------------------------------------------------------------
-%%
-%% This work may be distributed and/or modified under the
-%% conditions of the LaTeX Project Public License, either version 1.3
-%% of this license or (at your option) any later version.
-%% The latest version of this license is in
-%% http://www.latex-project.org/lppl.txt
-%% and version 1.3 or later is part of all distributions of LaTeX
-%% version 2003/12/01 or later.
-%%
-%% This work has the LPPL maintenance status "maintained".
-%%
-%% This Current Maintainer of this work is Axel Sommerfeldt.
-%%
-%% This work consists of the files
-%% CHANGELOG, README, SUMMARY, caption.ins,
-%% caption.dtx, caption2.dtx, caption3.dtx,
-%% bicaption.dtx, ltcaption.dtx, subcaption.dtx,
-%% newfloat.dtx, and totalcount.dtx
-%% the derived files
-%% caption.sty, caption2.sty, caption3.sty,
-%% bicaption.sty, ltcaption.sty, subcaption.sty,
-%% newfloat.sty, and totalcount.sty
-%% and the user manuals
-%% caption-deu.tex, caption-eng.tex, and caption-rus.tex.
-%%
-\NeedsTeXFormat{LaTeX2e}[1994/12/01]
-\def\caption@tempa$Id: #1 #2 #3-#4-#5 #6${%
- \def\caption@tempa{#3/#4/#5 }\def\caption@tempb{#2 }}
-\caption@tempa $Id: newfloat.dtx 109 2015-09-17 09:29:07Z sommerfeldt $
-\ProvidesPackage{newfloat}[\caption@tempa v1.1-\caption@tempb Defining new floating environments (AR)]
-\newcommand*\newfloat@Info[1]{%
- \PackageInfo{newfloat}{#1}}
-\newcommand*\newfloat@InfoNoLine[1]{%
- \newfloat@Info{#1\@gobble}}
-\newcommand*\newfloat@Error[1]{%
- \PackageError{newfloat}{#1}\newfloat@eh}
-\newcommand*\newfloat@eh{%
- If you do not understand this error, please take a closer look\MessageBreak
- at the documentation of the `newfloat' package.\MessageBreak\@ehc}
-\RequirePackage{keyval}[1997/11/10]
-\newcommand*\newfloat@def[2]{%
- \newfloat@ifundefined{#1}{%
- \@namedef{#1}{#2}}}
-\newcommand*\newfloat@let[2]{%
- \newfloat@ifundefined{#1}{%
- \expandafter\let\csname #1\endcsname#2}}
-\newcommand*\newfloat@ifundefined[2]{%
- \@ifundefined{#1}{#2}{%
- \newfloat@Info{%
- \expandafter\string\csname#1\endcsname\space is already defined}}}
-\newcommand*\DeclareFloatingEnvironment{%
- \@testopt\@DeclareFloatingEnvironment{}}
-\@onlypreamble\DeclareFloatingEnvironment
-\def\@DeclareFloatingEnvironment[#1]#2{%
- \newfloat@Info{New float `#2' with options `#1'}%
- \newfloat@ifundefined{c@#2}{\newcounter{#2}}%
- \ifdefined\c@float@type % from float package
- \expandafter\edef\csname ftype@#2\endcsname{\the\value{float@type}}%
- \addtocounter{float@type}{\value{float@type}}%
- \else\ifdefined\c@newflo@tctr % from memoir document class
- \expandafter\edef\csname ftype@#2\endcsname{\the\c@newflo@tctr}%
- \advance\c@newflo@tctr \c@newflo@tctr
- \else
- \ifdefined\newfloat@ftype \else
- \newcount\newfloat@ftype
- \newfloat@ftype=8\relax
- \fi
- \expandafter\xdef\csname ftype@#2\endcsname{\the\newfloat@ftype}%
- \advance\newfloat@ftype\newfloat@ftype
- \fi\fi
- \newfloat@Info{float type `#2'=\@nameuse{ftype@#2}}%
- \newfloat@def{fnum@#2}%
- {\@nameuse{#2name}\nobreakspace\@nameuse{the#2}\@nameuse{autodot}}%
- \newfloat@capitalize\newfloat@Type{#2}%
- \newfloat@let{#2name}{\newfloat@Type}%
- \newfloat@def{fleg#2}{\@nameuse{#2name}}% legend naming (memoir)
- \newfloat@ifundefined{flegtoc#2}{\@namedef{flegtoc#2}##1{}}%
- \ifcsname @tufte@float\endcsname
- \newenvironment{#2}[1][htbp]%
- {\begin{@tufte@float}[##1]{#2}{}}%
- {\end{@tufte@float}}%
- \newenvironment{#2*}[1][htbp]%
- {\begin{@tufte@float}[##1]{#2}{star}}%
- {\end{@tufte@float}}%
- \else
- \newenvironment{#2}{\@float{#2}}{\end@float}%
- \newenvironment{#2*}{\@dblfloat{#2}}{\end@dblfloat}%
- \fi
- \newfloat@def{listof#2}{\newfloat@listof{#2}}%
- \newfloat@def{listof#2s}{\@nameuse{listof#2}}%
- \newfloat@def{listof#2es}{\@nameuse{listof#2s}}%
- \newfloat@def{newfloat@listof#2@hook}{}%
- \ifdefined\l@figure
- \newfloat@let{l@#2}{\l@figure}%
- \else
- \newfloat@def{l@#2}{\@dottedtocline{1}{1.5em}{2.3em}}%
- \fi
- \edef\newfloat@tempa{List of \newfloat@Type s}%
- \newfloat@let{list#2name}{\newfloat@tempa}%
- \expandafter\let\csname fst@#2\endcsname\@undefined
- \newfloat@ifundefined{fps@#2}{\newfloat@setplacement{#2}{tbp}}%
- \newfloat@ifundefined{ext@#2}{\newfloat@setfileext{#2}{lo#2}}%
- \newfloat@setoptions*{#2}{#1}%
- \@expandtwoargs\newfloat@announce{#2}{\@nameuse{ext@#2}}%
- \@ifnextchar[\newfloat@DFE@setname\relax}
-\@onlypreamble\@DeclareFloatingEnvironment
-\def\newfloat@DFE@setname[#1]{%
- \KV@@newfloat@name{#1}%
- \@ifnextchar[\newfloat@DFE@setlistname\relax}
-\@onlypreamble\newfloat@DFE@setname
-\def\newfloat@DFE@setlistname[#1]{%
- \KV@@newfloat@listname{#1}}
-\@onlypreamble\newfloat@DFE@setlistname
-\newcommand*\newfloat@capitalize[2]{%
- \edef\newfloat@tempa{\gdef\noexpand#1{\@car#2\@nil}}%
- \uppercase\expandafter{\newfloat@tempa}%
- \edef\newfloat@tempa{%
- \noexpand\g@addto@macro\noexpand#1{\@cdr#2\@nil}}%
- \newfloat@tempa}
-\newcommand*\newfloat@listof[1]{%
- \@expandtwoargs\newfloat@list@of{#1}{\@nameuse{ext@#1}}}
-\newcommand*\newfloat@list@of[2]{%
- \begingroup
- \expandafter\let\expandafter\listfigurename\csname list#1name\endcsname
- \def\ext@figure{#2}%
- \let\newfloat@starttoc\@starttoc
- \def\@starttoc##1{\newfloat@starttoc{#2}}%
- \let\newfloat@listoftoc\listoftoc
- \def\listoftoc##1{\newfloat@listoftoc{#2}}%
- \@nameuse{newfloat@listof#1@hook}%
- \listoffigures
- \endgroup}
-\newcommand*\newfloat@setoptions{%
- \@ifstar
- {\newfloat@@setoptions\@firstofone}%
- {\newfloat@@setoptions\@gobble}}
-\newcommand*\newfloat@@setoptions[3]{%
- \let\newfloat@within@value\@undefined
- \let\newfloat@chapterlistsgaps@value\@undefined
- #1{\KV@@newfloat@within\newfloat@within@default}% set default value for new floats
- \def\newfloat@type{#2}%
- \setkeys{@newfloat}{#3}%
- \ifx\newfloat@within@value\@undefined \else
- \newfloat@setoption{within}\newfloat@within@value
- \fi
- \ifx\newfloat@chapterlistsgaps@value\@undefined \else
- \newfloat@setoption{chapterlistsgaps}\newfloat@chapterlistsgaps@value
- \fi}
-\newcommand*\newfloat@within@default{%
- \ifcsname c@chapter\endcsname chapter\else none\fi}
-\@onlypreamble\newfloat@within@default
-\newcommand*\newfloat@setoption[1]{%
- \edef\caption@tempa{\noexpand\@nameuse{newfloat@set#1}{\newfloat@type}}%
- \caption@tempa}
-\newcommand*\newfloat@setfileext[2]{%
- \@namedef{ext@#1}{#2}}
-\define@key{@newfloat}{fileext}{%
- \newfloat@setoption{fileext}{#1}}
-\newcommand*\newfloat@setlistname[2]{%
- \@namedef{list#1name}{#2}}
-\define@key{@newfloat}{listname}{%
- \newfloat@setoption{listname}{#1}}
-\newcommand*\newfloat@setname[2]{%
- \newfloat@@setname{#1}{#2}%
- \begingroup
- \ifcsname languagename\endcsname
- \ifcsname captions\languagename\endcsname
- \expandafter\g@addto@macro\csname captions\languagename\endcsname
- {\newfloat@@setname{#1}{#2}}%
- \fi
- \fi
- \endgroup}
-%%\AtBeginDocument{\let\newfloat@setname\newfloat@@setname}
-\newcommand*\newfloat@@setname[2]{%
- \@namedef{#1name}{#2}}
-\define@key{@newfloat}{name}{%
- \newfloat@setoption{name}{#1}}
-\newcommand*\newfloat@setplacement[2]{%
- \@namedef{fps@#1}{#2}}
-\define@key{@newfloat}{placement}{%
- \newfloat@setoption{placement}{#1}}
-\newcommand*\newfloat@setwithin[2]{%
- \ifcsname c@chapter\endcsname
- \@removefromreset{#1}{chapter}%
- \fi
- \@removefromreset{#1}{section}%
- \edef\@tempa{#2}%
- \ifx\@tempa\@empty
- \def\@tempa{none}%
- \fi
- \def\@tempb{none}%
- \ifx\@tempa\@tempb
- \ifcsname c@chapter\endcsname
- \@chapterlistsgap@off{#1}%
- \fi
- \newfloat@@setwithin{#1}{}{}%
- \else
- \def\@tempb{chapter}%
- \ifx\@tempa\@tempb
- \@addtoreset{#1}{chapter}%
- \@chapterlistsgap@on{#1}%
- \newfloat@@setwithin{#1}{\ifnum\c@chapter>\z@ \thechapter.\fi}{\theHchapter.}%
- \else
- \def\@tempb{section}%
- \ifx\@tempa\@tempb
- \@addtoreset{#1}{section}%
- \ifcsname c@chapter\endcsname
- \@addtoreset{#1}{chapter}%
- \@chapterlistsgap@on{#1}%
- \newfloat@@setwithin{#1}{\thesection.}{\theHsection.}%
- \else
- \newfloat@@setwithin{#1}{\ifnum\c@section>\z@ \thesection.\fi}{\theHsection.}%
- \fi
- \else
- \newfloat@Error{Invalid value `#2' for option `within'}%
- \fi
- \fi
- \fi}
-\newcommand*\newfloat@@setwithin[3]{%
- \global\@namedef{the#1}{#2\arabic{#1}}%
- \global\@namedef{theH#1}{#3\arabic{#1}}}
-\define@key{@newfloat}{within}{%
- \def\newfloat@within@value{#1}}
-\newcommand*\newfloat@setwithout[1]{%
- \newfloat@setwithin{#1}{none}}
-\define@key{@newfloat}{without}[]{%
- \def\newfloat@within@value{none}}
-\newcommand*\newfloat@setchapterlistsgaps[2]{%
- \edef\@tempa{#2}%
- \def\@tempb{off}%
- \ifx\@tempa\@tempb
- \@chapterlistsgap@off{#1}%
- \else
- \def\@tempb{on}%
- \ifx\@tempa\@tempb
- \@chapterlistsgap@on{#1}%
- \else
- \newfloat@Error{Invalid value `#2' for option `chapterlistsgaps'}%
- \fi
- \fi}
-\define@key{@newfloat}{chapterlistsgaps}{%
- \def\newfloat@chapterlistsgaps@value{#1}}
-\providecommand*\@removefromreset[2]{{%
- \expandafter\let\csname c@#1\endcsname\@removefromreset
- \def\@elt##1{%
- \expandafter\ifx\csname c@##1\endcsname\@removefromreset
- \else
- \noexpand\@elt{##1}%
- \fi}%
- \expandafter\xdef\csname cl@#2\endcsname{%
- \csname cl@#2\endcsname}}}
-\newcommand*\newfloat@announce[2]{%
- \@cons\newfloat@list{{#1}}%
- \@cons\newfloat@@list{{#1}}%
- \newfloat@ifundefined{newfloat@ext@#2}{%
- \@namedef{newfloat@ext@#2}{#1}%
- \ifcsname c@lofdepth\endcsname
- \newfloat@ifundefined{c@#2depth}{%
- \newcounter{#2depth}%
- \setcounter{#2depth}{1}}%
- \fi
- \ifcsname addtotoclist\endcsname
- \addtotoclist[float]{#2}%
- \newfloat@def{listof#2name}{\@nameuse{list#1name}}%
- \fi
- }%
- \ifcsname contentsuse\endcsname
- \contentsuse{#1}{#2}%
- \fi
- \newfloat@hook{#1}}
-\@onlypreamble\newfloat@announce
-\newcommand*\newfloat@@list{}
-\newcommand*\SetupFloatingEnvironment[1]{%
- \newfloat@addtolist{#1}%
- \newfloat@setoptions{#1}}
-\newcommand\ForEachFloatingEnvironment{%
- \@ifstar
- {\@ForEachFloatingEnvironment\@gobble}%
- {\@ForEachFloatingEnvironment\@iden}}
-\newcommand\@ForEachFloatingEnvironment[2]{%
- \def\@elt##1{#2}%
- \newfloat@list
- \let\@elt\relax
- #1{\newfloat@addtohook{#2}}}
-\providecommand\newfloat@addtohook[1]{%
- \toks@=\expandafter{\newfloat@hook{##1}#1}%
- \edef\@tempa{\def\noexpand\newfloat@hook####1{\the\toks@}}%
- \@tempa}
-\providecommand*\newfloat@hook[1]{}
-\newcommand\PrepareListOf[1]{%
- \expandafter\g@addto@macro\csname newfloat@listof#1@hook\endcsname}
-\@onlypreamble\PrepareListOf
-\newcommand*\newfloat@list{}
-\newcommand*\newfloat@addtolist[1]{%
- \newfloat@ifinlist{#1}{}{%
- \ifcsname ext@#1\endcsname
- \@cons\newfloat@list{{#1}}%
- \@namedef{newfloat@ext@\@nameuse{ext@#1}}{#1}%
- \newfloat@let{@ifchapterlistsgap@#1}{\@iden}%
- \else
- \newfloat@Error{`#1' does not seem to be a floating environment}%
- \fi}}
-\newcommand*\newfloat@ifinlist[1]{%
- \let\next\@secondoftwo
- \begingroup
- \expandafter\let\csname c@#1\endcsname\newfloat@ifinlist
- \def\@elt##1{%
- \expandafter\ifx\csname c@##1\endcsname\newfloat@ifinlist
- \global\let\next\@firstoftwo
- \fi}%
- \newfloat@list
- \endgroup
- \next}
-\ifcsname ext@figure\endcsname
- \newfloat@addtolist{figure}
-\fi
-\ifcsname ext@table\endcsname
- \newfloat@addtolist{table}
-\fi
-\ifcsname @chapter\endcsname
- \providecommand*\@chapterlistsgap{10\p@}%
- \providecommand*\@addchapterlistsgap[2]{%
- \@nameuse{@ifchapterlistsgap@#1}{% if switched on
- \@@addchapterlistsgap{#1}{#2}}}
- \providecommand*\@@addchapterlistsgap[2]{%
- \@ifundefined{@addchapterlistsgap@#2}{% only once per extension
- \@namedef{@addchapterlistsgap@#2}{#1}%
- \@@@addchapterlistsgap{#2}}{}}
- \providecommand*\@@@addchapterlistsgap[1]{%
- \ifdim \@chapterlistsgap>\z@
- \addtocontents{#1}{\protect\addvspace{\@chapterlistsgap}}%
- \fi}
- \providecommand*\@addchapterlistsgaps{%
- \begingroup
- \def\@elt##1{%
- \@expandtwoargs\@addchapterlistsgap{##1}{\@nameuse{ext@##1}}}%
- \newfloat@list
- \endgroup}
- \providecommand*\@chapterlistsgap@off[1]{%
- \expandafter\let\csname @ifchapterlistsgap@#1\endcsname\@gobble
- \ifcsname unsettoc\endcsname
- \@expandtwoargs\unsettoc{\@nameuse{ext@#1}}{chapteratlist}%
- \fi}
- \providecommand*\@chapterlistsgap@on[1]{%
- \expandafter\let\csname @ifchapterlistsgap@#1\endcsname\@iden
- \ifcsname setuptoc\endcsname
- \@expandtwoargs\setuptoc{\@nameuse{ext@#1}}{chapteratlist}%
- \fi}
-\fi
-\define@key{newfloat}{chapterlistsgap}{%
- \renewcommand*\@chapterlistsgap{#1}}
-\define@key{newfloat}{within}{%
- \def\newfloat@within@default{#1}% set new default value
- \def\@elt##1{\newfloat@setwithin{##1}{#1}}%
- \newfloat@list
- \let\@elt\relax}
-\define@key{newfloat}{without}[]{%
- \KV@newfloat@within{none}}
-\def\@elt#1{%
- \define@key{newfloat}{#1name}{%
- \newfloat@setname{#1}{##1}}%
- \define@key{newfloat}{list#1name}{%
- \newfloat@setname{list#1}{##1}}%
- \define@key{newfloat}{#1within}{%
- \newfloat@setwithin{#1}{##1}}%
- \define@key{newfloat}{#1without}[]{%
- \newfloat@setwithout{#1}}%
-}%
-\newfloat@list
-\let\@elt\relax
-\define@key{newfloat}{planb}[true]{%
- \def\@tempa{#1}%
- \def\@tempb{false}%
- \ifx\@tempa\@tempb
- \let\newfloat@ifplanb\@gobble
- \else
- \def\@tempb{true}%
- \ifx\@tempa\@tempb
- \let\newfloat@ifplanb\@iden
- \else
- \newfloat@Error{Invalid value `#1' for option `planb'}%
- \fi
- \fi}
-\define@key{newfloat}{planb-fileext}{%
- \newfloat@Info{Setting Plan B file extension to `#1'}
- \xdef\newfloat@addtocontents@ext{#1}}
-
-\let\@tempc\relax
-\@expandtwoargs\setkeys{newfloat}{planb,\@ptionlist{\@currname.\@currext}}%
-\AtEndOfPackage{\let\@unprocessedoptions\relax}
-\newcommand*\newfloatsetup{\setkeys{newfloat}}
-\newcommand\newfloat@replace@chapter[2]{%
- \begingroup
- \let\if@twocolumn\iffalse
- \let\if@mainmatter\iffalse
- \let\if@thema\iffalse
- \def\@tempa[##1]##2{#1}%
- \ifx\@tempa\@chapter
- \gdef\@chapter[##1]##2{#2}%
- \global\let\newfloat@replace@chapter\@gobbletwo
- \else\ifx\@tempa\Hy@org@chapter
- \gdef\Hy@org@chapter[##1]##2{#2}%
- \global\let\newfloat@replace@chapter\@gobbletwo
- \fi\fi
- \endgroup}
-\ifcsname @chapter\endcsname \else
- \let\newfloat@replace@chapter\@gobbletwo
-\fi
-\newfloat@replace@chapter{%
- \ifnum \c@secnumdepth >\m@ne
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}#1}%
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \chaptermark{#1}%
- \addtocontents{lof}{\protect\addvspace{10\p@}}%
- \addtocontents{lot}{\protect\addvspace{10\p@}}%
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi
-}{%
- \ifnum \c@secnumdepth >\m@ne
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}#1}%
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \chaptermark{#1}%
- \@addchapterlistsgaps
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi}
-\newfloat@replace@chapter{%
- \ifnum \c@secnumdepth >\m@ne
- \if@mainmatter
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}#1}%
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \chaptermark{#1}%
- \addtocontents{lof}{\protect\addvspace{10\p@}}%
- \addtocontents{lot}{\protect\addvspace{10\p@}}%
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi
-}{%
- \ifnum \c@secnumdepth >\m@ne
- \if@mainmatter
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}#1}%
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \chaptermark{#1}%
- \@addchapterlistsgaps
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi}
-\newfloat@replace@chapter{%
- \refstepcounter{chapter}%
- \ifnum\c@secnumdepth<\z@ \let\@secnumber\@empty
- \else \let\@secnumber\thechapter \fi
- \typeout{\chaptername\space\@secnumber}%
- \def\@toclevel{0}%
- \ifx\chaptername\appendixname \@tocwriteb\tocappendix{chapter}{#2}%
- \else \@tocwriteb\tocchapter{chapter}{#2}\fi
- \chaptermark{#1}%
- \addtocontents{lof}{\protect\addvspace{10\p@}}%
- \addtocontents{lot}{\protect\addvspace{10\p@}}%
- \@makechapterhead{#2}\@afterheading
-}{%
- \refstepcounter{chapter}%
- \ifnum\c@secnumdepth<\z@ \let\@secnumber\@empty
- \else \let\@secnumber\thechapter \fi
- \typeout{\chaptername\space\@secnumber}%
- \def\@toclevel{0}%
- \ifx\chaptername\appendixname \@tocwriteb\tocappendix{chapter}{#2}%
- \else \@tocwriteb\tocchapter{chapter}{#2}\fi
- \chaptermark{#1}%
- \@addchapterlistsgaps
- \@makechapterhead{#2}\@afterheading}
-\@ifpackageloaded{tocbasic}{%
- \let\newfloat@replace@chapter\@gobbletwo}{}
-\ifcsname insertchapterspace\endcsname
- \renewcommand*\insertchapterspace{\@addchapterlistsgaps}
- \let\newfloat@replace@chapter\@gobbletwo
-\fi
-\newfloat@replace@chapter{%
- \ifnum \c@secnumdepth >\m@ne
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}\toc@font0 #1}%
- \else
- \addcontentsline{toc}{chapter}{\toc@font0 #1}%
- \fi
- \chaptermark{#1}%
- \addtocontents{lof}{\protect\addvspace{10\p@}}%
- \addtocontents{lot}{\protect\addvspace{10\p@}}%
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi
-}{%
- \ifnum \c@secnumdepth >\m@ne
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}\toc@font0 #1}%
- \else
- \addcontentsline{toc}{chapter}{\toc@font0 #1}%
- \fi
- \chaptermark{#1}%
- \@addchapterlistsgaps
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi}
- % boek(3).cls [2004/06/07 v2.1a NTG LaTeX document class]
-\newfloat@replace@chapter{%
- \ifnum \c@secnumdepth >\m@ne
- \if@mainmatter
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}\toc@font0 #1}%
- \else
- \addcontentsline{toc}{chapter}{\toc@font0 #1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{\toc@font0 #1}%
- \fi
- \chaptermark{#1}%
- \addtocontents{lof}{\protect\addvspace{10\p@}}%
- \addtocontents{lot}{\protect\addvspace{10\p@}}%
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi
-}{%
- \ifnum \c@secnumdepth >\m@ne
- \if@mainmatter
- \refstepcounter{chapter}%
- \typeout{\@chapapp\space\thechapter.}%
- \addcontentsline{toc}{chapter}%
- {\protect\numberline{\thechapter}\toc@font0 #1}%
- \else
- \addcontentsline{toc}{chapter}{\toc@font0 #1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{\toc@font0 #1}%
- \fi
- \chaptermark{#1}%
- \@addchapterlistsgaps
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi}
-\newfloat@replace@chapter{%
- \ifnum \c@secnumdepth >\m@ne
- \if@mainmatter
- \refstepcounter{chapter}%
- \typeout{\chaptername\space\thechapter.}
- \if@thema
- \ifx\@shortauthor\@empty
- \addcontentsline{toc}{chapter}{%
- \protect\numberline{\thechapter.}#1}%
- \else
- \addcontentsline{toc}{chapter}{%
- \protect\numberline{\thechapter.}%
- \@shortauthor\hfill\mbox{}\vskip\normallineskip #1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{%
- \protect\numberline{\thechapter.}#1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{#1}
- \fi
- \else
- \addcontentsline{toc}{chapter}{#1}
- \fi
- \chaptermark{#1}
- \addtocontents{lof}{\protect\addvspace{10pt}}
- \addtocontents{lot}{\protect\addvspace{10pt}}
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]
- \else
- \@makechapterhead{#2}
- \@afterheading
- \fi
-}{%
- \ifnum \c@secnumdepth >\m@ne
- \if@mainmatter
- \refstepcounter{chapter}%
- \typeout{\chaptername\space\thechapter.}%
- \if@thema
- \ifx\@shortauthor\@empty
- \addcontentsline{toc}{chapter}{%
- \protect\numberline{\thechapter.}#1}%
- \else
- \addcontentsline{toc}{chapter}{%
- \protect\numberline{\thechapter.}%
- \@shortauthor\hfill\mbox{}\vskip\normallineskip #1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{%
- \protect\numberline{\thechapter.}#1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \else
- \addcontentsline{toc}{chapter}{#1}%
- \fi
- \chaptermark{#1}%
- \@addchapterlistsgaps
- \if@twocolumn
- \@topnewpage[\@makechapterhead{#2}]%
- \else
- \@makechapterhead{#2}%
- \@afterheading
- \fi}
-\ifx\newfloat@replace@chapter\@gobbletwo \else
- \newfloat@InfoNoLine{%
- Unsupported document class, or \noexpand\@chapter\MessageBreak
- was already redefined by another package}
- \newfloat@InfoNoLine{\string\@chapter\space=\space\meaning\@chapter}
- \newfloat@InfoNoLine{\string\Hy@org@chapter\space=\space\meaning\Hy@org@chapter}
- \newfloat@ifplanb{%
- \newfloat@InfoNoLine{Trying Plan B..}%
- \let\newfloat@addtocontents@ORI\addtocontents
- \long\def\addtocontents#1#2{%
- \newfloat@addtocontents{#1}{#2}#2\addvspace\newfloat@nil}%
- \long\def\newfloat@addtocontents#1#2#3\addvspace#4\newfloat@nil{%
- \def\newfloat@tempa{#4}%
- \ifx\newfloat@tempa\@empty
- \newfloat@addtocontents@ORI{#1}{#2}%
- \else
- \ifx\newfloat@addtocontents@ext\@undefined
- \newfloat@Info{Setting Plan B file extension to `#1'...}%
- \xdef\newfloat@addtocontents@ext{#1}%
- \fi
- \edef\newfloat@tempa{#1}%
- \ifx\newfloat@tempa\newfloat@addtocontents@ext
- \begingroup
- \let\addtocontents\newfloat@addtocontents@ORI
- \@addchapterlistsgaps
- \endgroup
- \fi
- \fi}}
-\fi
-\newcommand\newfloat@ForEachNew[2][newfloat@@list]{%
- \AtBeginDocument{%
- \ifcsname#1\endcsname
- \def\@elt##1{#2}%
- \newfloat@@list
- \let\@elt\relax
- \fi}}%
-\@onlypreamble\newfloat@ForEachNew
-%% \begin{macrocode}
-\newfloat@ForEachNew[float@exts]{%
- \@nameuse{@ifchapterlistsgap@#1}{% if switched on
- \let\float@do=\relax
- \edef\@tempa{%
- \noexpand\float@exts{\the\float@exts\float@do{\@nameuse{ext@#1}}}}%
- \@tempa}}
-\newfloat@ForEachNew[FP@floatBegin]{%
- \newcounter{FP@#1C}%
- \newenvironment{FP#1}{\FP@floatBegin{#1}}{\FP@floatEnd}}
-\providecommand*\ext@lstlisting{lol}%
-\newfloat@ForEachNew[@rotfloat]{%
- \newenvironment{sideways#1}{\@rotfloat{#1}}{\end@rotfloat}%
- \newenvironment{sideways#1*}{\@rotdblfloat{#1}}{\end@rotdblfloat}}
-\newcommand*\newfloat@For@SC[2]{%
- \def#1{b}% = \sidecaptionvpos{#2}{b} (v1.6)
- \newenvironment{SC#2}%
- {\SC@float[#1]{#2}}{\endSC@float}%
- \newenvironment{SC#2*}%
- {\SC@dblfloat[#1]{#2}}{\endSC@dblfloat}}
-\@onlypreamble\newfloat@For@SC
-\newfloat@ForEachNew[SC@float]{%
- \expandafter\newfloat@For@SC\csname SC@#1@vpos\endcsname{#1}}
-\newfloat@ForEachNew[wrapfloat]{%
- \newenvironment{wrap#1}{\wrapfloat{#1}}{\endwrapfloat}}
-\endinput
-%%
-%% End of file `newfloat.sty'.
diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty
index 956924e99..e612cf5ef 100644
--- a/sphinx/texinputs/sphinx.sty
+++ b/sphinx/texinputs/sphinx.sty
@@ -6,18 +6,34 @@
%
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
-\ProvidesPackage{sphinx}[2010/01/15 LaTeX package (Sphinx markup)]
+\ProvidesPackage{sphinx}[2016/06/10 LaTeX package (Sphinx markup)]
+
+% this is the \ltx@ifundefined of ltxcmds.sty, which is loaded by
+% hyperref.sty, but we need it before, and initial ltxcmds.sty
+% as in TL2009/Debian had wrong definition.
+\newcommand{\spx@ifundefined}[1]{%
+ \ifcsname #1\endcsname
+ \expandafter\ifx\csname #1\endcsname\relax
+ \expandafter\expandafter\expandafter\@firstoftwo
+ \else
+ \expandafter\expandafter\expandafter\@secondoftwo
+ \fi
+ \else
+ \expandafter\@firstoftwo
+ \fi
+}
+\RequirePackage{graphicx}
\@ifclassloaded{memoir}{}{\RequirePackage{fancyhdr}}
+% for \text macro and \iffirstchoice@ conditional even if amsmath not loaded
+\RequirePackage{amstext}
\RequirePackage{textcomp}
\RequirePackage{titlesec}
\RequirePackage{tabulary}
\RequirePackage{makeidx}
% For framing code-blocks and warning type notices, and shadowing topics
\RequirePackage{framed}
-\newif\ifSphinx@inframed % flag set if we are in a framed environment
-\RequirePackage{ifthen}
% The xcolor package draws better fcolorboxes around verbatim code
\IfFileExists{xcolor.sty}{
\RequirePackage{xcolor}
@@ -26,12 +42,16 @@
}
% For highlighted code.
\RequirePackage{fancyvrb}
+\fvset{fontsize=\small}
% For table captions.
\RequirePackage{threeparttable}
% Handle footnotes in tables.
\RequirePackage{footnote}
\makesavenoteenv{tabulary}
-% For floating figures in the text.
+% For the H specifier. Do not \restylefloat{figure}, it breaks Sphinx code
+% for allowing figures in tables.
+\RequirePackage{float}
+% For floating figures in the text. Better to load after float.
\RequirePackage{wrapfig}
% Separate paragraphs by space by default.
\RequirePackage{parskip}
@@ -61,20 +81,20 @@
\newcount\pdfoutput\pdfoutput=0
\fi
-\RequirePackage{graphicx}
-
% for PDF output, use colors and maximal compression
-\newif\ifsphinxpdfoutput\sphinxpdfoutputfalse
-\ifx\pdfoutput\undefined\else\ifcase\pdfoutput
+\newif\ifsphinxpdfoutput % used in \maketitle
+\ifx\pdfoutput\undefined\else
+ \ifnum\pdfoutput=\z@
\let\py@NormalColor\relax
\let\py@TitleColor\relax
-\else
+ \else
\sphinxpdfoutputtrue
\input{pdfcolor}
\def\py@NormalColor{\color[rgb]{0.0,0.0,0.0}}
\def\py@TitleColor{\color{TitleColor}}
\pdfcompresslevel=9
-\fi\fi
+ \fi
+\fi
% XeLaTeX can do colors, too
\ifx\XeTeXrevision\undefined\else
@@ -109,9 +129,10 @@
% Use this to set the font family for headers and other decor:
\newcommand{\py@HeaderFamily}{\sffamily\bfseries}
+\newcommand{\sphinxSetHeaderFamily}[1]{\renewcommand{\py@HeaderFamily}{#1}}
% Redefine the 'normal' header/footer style when using "fancyhdr" package:
-\@ifundefined{fancyhf}{}{
+\spx@ifundefined{fancyhf}{}{
% Use \pagestyle{normal} as the primary pagestyle for text.
\fancypagestyle{normal}{
\fancyhf{}
@@ -122,9 +143,8 @@
\renewcommand{\headrulewidth}{0.4pt}
\renewcommand{\footrulewidth}{0.4pt}
% define chaptermark with \@chappos when \@chappos is available for Japanese
- \ifx\@chappos\undefined\else
- \def\chaptermark##1{\markboth{\@chapapp\space\thechapter\space\@chappos\space ##1}{}}
- \fi
+ \spx@ifundefined{@chappos}{}
+ {\def\chaptermark##1{\markboth{\@chapapp\space\thechapter\space\@chappos\space ##1}{}}}
}
% Update the plain style so we get the page number & footer line,
% but not a chapter or section title. This is to keep the first
@@ -138,28 +158,45 @@
}
% Some custom font markup commands.
-%
-\newcommand{\strong}[1]{{\textbf{#1}}}
-\newcommand{\code}[1]{\texttt{#1}}
-\newcommand{\bfcode}[1]{\code{\bfseries#1}}
-\newcommand{\email}[1]{\textsf{#1}}
-\newcommand{\tablecontinued}[1]{\textsf{#1}}
-\newcommand{\titleref}[1]{\emph{#1}}
-\newcommand{\menuselection}[1]{\emph{#1}}
-\newcommand{\accelerator}[1]{\underline{#1}}
-\newcommand{\crossref}[1]{\emph{#1}}
-\newcommand{\termref}[1]{\emph{#1}}
-
+% *** the macros without \sphinx prefix are still defined at bottom of file ***
+\newcommand{\sphinxstrong}[1]{{\textbf{#1}}}
+% let \sphinxcode and \sphinxbfcode use straight quotes. \@noligs patched by upquote,
+% but needs protection in "moving arguments" such as for captions.
+% Use \scantokens to handle e.g. \item[{\sphinxcode{'fontenc'}}]
+\DeclareRobustCommand{\sphinxcode}[1]{{\@noligs\scantokens{\texttt{#1}\relax}}}
+\newcommand{\sphinxbfcode}[1]{\sphinxcode{\bfseries#1}}
+\newcommand{\sphinxemail}[1]{\textsf{#1}}
+\newcommand{\sphinxtablecontinued}[1]{\textsf{#1}}
+\newcommand{\sphinxtitleref}[1]{\emph{#1}}
+\newcommand{\sphinxmenuselection}[1]{\emph{#1}}
+\newcommand{\sphinxaccelerator}[1]{\underline{#1}}
+\newcommand{\sphinxcrossref}[1]{\emph{#1}}
+\newcommand{\sphinxtermref}[1]{\emph{#1}}
+
+% miscellaneous related to footnotes
\newcommand*{\sphinxAtStartFootnote}{\mbox{ }}
-
-% Redefine the Verbatim environment to allow border and background colors
-% and to handle the top caption in a non separable by pagebreak way.
-% The original environment is still used for verbatims within tables.
-\let\OriginalVerbatim=\Verbatim
-\let\endOriginalVerbatim=\endVerbatim
-
-\newcommand\Sphinx@colorbox [2]{%
-% #1 will be \fcolorbox or, for first part of frame: \Sphinx@fcolorbox
+% Support large numbered footnotes in minipage (cf. admonitions)
+\def\thempfootnote{\arabic{mpfootnote}}
+
+% Preparations for sphinxVerbatim environment, which is a wrapper of fancyvrb
+% Verbatim with framing allowing pagebreaks, with border and background colors
+% and possibly also a top caption, non separable by pagebreak.
+
+% For maintaining compatibility with Sphinx < 1.5, we define and use these
+% when (unmodified) Verbatim will be needed. But Sphinx >= 1.5 does not modify
+% original Verbatim anyhow.
+\let\OriginalVerbatim \Verbatim
+\let\endOriginalVerbatim\endVerbatim
+
+\newif\ifspx@inframed % flag set if we are already in a framed environment
+\newdimen\sphinxverbatimsep \sphinxverbatimsep \fboxsep % default 3pt
+\newdimen\sphinxverbatimborder\sphinxverbatimborder\fboxrule % default 0.4pt
+\newif\ifsphinxverbatimwithframe \sphinxverbatimwithframetrue
+\newif\ifsphinxverbatimwrapslines \sphinxverbatimwrapslinestrue
+% if forced use of minipage encapsulation is needed (e.g. table cells)
+\newif\ifsphinxverbatimwithminipage \sphinxverbatimwithminipagefalse
+\newcommand\spx@colorbox [2]{%
+% #1 will be \fcolorbox or, for first part of frame: \spx@fcolorbox
% let the framing obey the current indentation (adapted from framed.sty's code).
\hskip\@totalleftmargin
\hskip-\fboxsep\hskip-\fboxrule
@@ -168,100 +205,102 @@
\hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth
}
% use of \color@b@x here is compatible with both xcolor.sty and color.sty
-\def\Sphinx@fcolorbox #1#2%
- {\color@b@x {\fboxsep\z@\color{#1}\Sphinx@VerbatimFBox}{\color{#2}}}%
-
-% The title is specified from outside as macro \SphinxVerbatimTitle.
-% \SphinxVerbatimTitle is reset to empty after each use of Verbatim.
-\newcommand*\SphinxVerbatimTitle {}
+\def\spx@fcolorbox #1#2%
+ {\color@b@x {\fboxsep\z@\color{#1}\spx@VerbatimFBox}{\color{#2}}}%
+
+% The title (caption) is specified from outside as macro \sphinxVerbatimTitle.
+% \sphinxVerbatimTitle is reset to empty after each use of Verbatim.
+\newcommand*\sphinxVerbatimTitle {}
+% This box to typeset the caption before framed.sty multiple passes for framing.
+\newbox\spx@VerbatimTitleBox
% Holder macro for labels of literal blocks. Set-up by LaTeX writer.
-\newcommand*\SphinxLiteralBlockLabel {}
-\newcommand*\SphinxSetupCaptionForVerbatim [2]
+\newcommand*\sphinxLiteralBlockLabel {}
+\newcommand*\sphinxSetupCaptionForVerbatim [1]
{%
- \needspace{\literalblockneedspace}%
-% insert a \label via \SphinxLiteralBlockLabel
+ \needspace{\sphinxliteralblockneedspace}%
+% insert a \label via \sphinxLiteralBlockLabel
% reset to normal the color for the literal block caption
% the caption inserts \abovecaptionskip whitespace above itself (usually 10pt)
% there is also \belowcaptionskip but it is usually zero, hence the \smallskip
- \def\SphinxVerbatimTitle
- {\py@NormalColor\captionof{#1}{\SphinxLiteralBlockLabel #2}\smallskip }%
+ \def\sphinxVerbatimTitle
+ {\py@NormalColor
+ \captionof{literalblock}{\sphinxLiteralBlockLabel #1}\smallskip }%
}
% Inspired and adapted from framed.sty's \CustomFBox with extra handling
-% of a non separable by pagebreak caption, and controlled counter stepping.
-\newif\ifSphinx@myfirstframedpass
-
-\long\def\Sphinx@VerbatimFBox#1{%
+% of a non separable by pagebreak caption.
+\long\def\spx@VerbatimFBox#1{%
\leavevmode
\begingroup
- % framed.sty does some measuring but this macro adds possibly a caption
- % use amsmath conditional to inhibit the caption counter stepping after
- % first pass
- \ifSphinx@myfirstframedpass\else\firstchoice@false\fi
\setbox\@tempboxa\hbox{\kern\fboxsep{#1}\kern\fboxsep}%
\hbox
{\lower\dimexpr\fboxrule+\fboxsep+\dp\@tempboxa
\hbox{%
- \vbox{\ifx\SphinxVerbatimTitle\empty\else
+ \vbox{\ifvoid\spx@VerbatimTitleBox\else
% add the caption in a centered way above possibly indented frame
% hide its width from framed.sty's measuring step
% note that the caption brings \abovecaptionskip top vertical space
\moveright\dimexpr\fboxrule+.5\wd\@tempboxa
- \hb@xt@\z@{\hss\begin{minipage}{\wd\@tempboxa}%
- \SphinxVerbatimTitle
- \end{minipage}\hss}\fi
- \hrule\@height\fboxrule\relax
- \hbox{\vrule\@width\fboxrule\relax
+ \hb@xt@\z@{\hss\unhcopy\spx@VerbatimTitleBox\hss}\fi
+ % draw frame border _latest_ to avoid pdf viewer issue
+ \kern\fboxrule
+ \hbox{\kern\fboxrule
\vbox{\vskip\fboxsep\copy\@tempboxa\vskip\fboxsep}%
- \vrule\@width\fboxrule\relax}%
- \hrule\@height\fboxrule\relax}%
+ \kern-\wd\@tempboxa\kern-\fboxrule
+ \vrule\@width\fboxrule
+ \kern\wd\@tempboxa
+ \vrule\@width\fboxrule}%
+ \kern-\dimexpr\fboxsep+\ht\@tempboxa+\dp\@tempboxa
+ +\fboxsep+\fboxrule\relax
+ \hrule\@height\fboxrule
+ \kern\dimexpr\fboxsep+\ht\@tempboxa+\dp\@tempboxa+\fboxsep\relax
+ \hrule\@height\fboxrule}%
}}%
\endgroup
- \global\Sphinx@myfirstframedpassfalse
}
% For linebreaks inside Verbatim environment from package fancyvrb.
-\newbox\Sphinxcontinuationbox
-\newbox\Sphinxvisiblespacebox
+\newbox\sphinxcontinuationbox
+\newbox\sphinxvisiblespacebox
% These are user customizable e.g. from latex_elements's preamble key.
% Use of \textvisiblespace for compatibility with XeTeX/LuaTeX/fontspec.
-\newcommand*\Sphinxvisiblespace {\textcolor{red}{\textvisiblespace}}
-\newcommand*\Sphinxcontinuationsymbol {\textcolor{red}{\llap{\tiny$\m@th\hookrightarrow$}}}
-\newcommand*\Sphinxcontinuationindent {3ex }
-\newcommand*\Sphinxafterbreak {\kern\Sphinxcontinuationindent\copy\Sphinxcontinuationbox}
+\newcommand*\sphinxvisiblespace {\textcolor{red}{\textvisiblespace}}
+\newcommand*\sphinxcontinuationsymbol {\textcolor{red}{\llap{\tiny$\m@th\hookrightarrow$}}}
+\newcommand*\sphinxcontinuationindent {3ex }
+\newcommand*\sphinxafterbreak {\kern\sphinxcontinuationindent\copy\sphinxcontinuationbox}
% Take advantage of the already applied Pygments mark-up to insert
% potential linebreaks for TeX processing.
% {, <, #, %, $, ' and ": go to next line.
% _, }, ^, &, >, - and ~: stay at end of broken line.
% Use of \textquotesingle for straight quote.
-\newcommand*\Sphinxbreaksatspecials {%
- \def\PYGZus{\discretionary{\char`\_}{\Sphinxafterbreak}{\char`\_}}%
- \def\PYGZob{\discretionary{}{\Sphinxafterbreak\char`\{}{\char`\{}}%
- \def\PYGZcb{\discretionary{\char`\}}{\Sphinxafterbreak}{\char`\}}}%
- \def\PYGZca{\discretionary{\char`\^}{\Sphinxafterbreak}{\char`\^}}%
- \def\PYGZam{\discretionary{\char`\&}{\Sphinxafterbreak}{\char`\&}}%
- \def\PYGZlt{\discretionary{}{\Sphinxafterbreak\char`\<}{\char`\<}}%
- \def\PYGZgt{\discretionary{\char`\>}{\Sphinxafterbreak}{\char`\>}}%
- \def\PYGZsh{\discretionary{}{\Sphinxafterbreak\char`\#}{\char`\#}}%
- \def\PYGZpc{\discretionary{}{\Sphinxafterbreak\char`\%}{\char`\%}}%
- \def\PYGZdl{\discretionary{}{\Sphinxafterbreak\char`\$}{\char`\$}}%
- \def\PYGZhy{\discretionary{\char`\-}{\Sphinxafterbreak}{\char`\-}}%
- \def\PYGZsq{\discretionary{}{\Sphinxafterbreak\textquotesingle}{\textquotesingle}}%
- \def\PYGZdq{\discretionary{}{\Sphinxafterbreak\char`\"}{\char`\"}}%
- \def\PYGZti{\discretionary{\char`\~}{\Sphinxafterbreak}{\char`\~}}%
+\newcommand*\sphinxbreaksatspecials {%
+ \def\PYGZus{\discretionary{\char`\_}{\sphinxafterbreak}{\char`\_}}%
+ \def\PYGZob{\discretionary{}{\sphinxafterbreak\char`\{}{\char`\{}}%
+ \def\PYGZcb{\discretionary{\char`\}}{\sphinxafterbreak}{\char`\}}}%
+ \def\PYGZca{\discretionary{\char`\^}{\sphinxafterbreak}{\char`\^}}%
+ \def\PYGZam{\discretionary{\char`\&}{\sphinxafterbreak}{\char`\&}}%
+ \def\PYGZlt{\discretionary{}{\sphinxafterbreak\char`\<}{\char`\<}}%
+ \def\PYGZgt{\discretionary{\char`\>}{\sphinxafterbreak}{\char`\>}}%
+ \def\PYGZsh{\discretionary{}{\sphinxafterbreak\char`\#}{\char`\#}}%
+ \def\PYGZpc{\discretionary{}{\sphinxafterbreak\char`\%}{\char`\%}}%
+ \def\PYGZdl{\discretionary{}{\sphinxafterbreak\char`\$}{\char`\$}}%
+ \def\PYGZhy{\discretionary{\char`\-}{\sphinxafterbreak}{\char`\-}}%
+ \def\PYGZsq{\discretionary{}{\sphinxafterbreak\textquotesingle}{\textquotesingle}}%
+ \def\PYGZdq{\discretionary{}{\sphinxafterbreak\char`\"}{\char`\"}}%
+ \def\PYGZti{\discretionary{\char`\~}{\sphinxafterbreak}{\char`\~}}%
}
% Some characters . , ; ? ! / are not pygmentized.
% This macro makes them "active" and they will insert potential linebreaks
-\newcommand*\Sphinxbreaksatpunct {%
- \lccode`\~`\.\lowercase{\def~}{\discretionary{\char`\.}{\Sphinxafterbreak}{\char`\.}}%
- \lccode`\~`\,\lowercase{\def~}{\discretionary{\char`\,}{\Sphinxafterbreak}{\char`\,}}%
- \lccode`\~`\;\lowercase{\def~}{\discretionary{\char`\;}{\Sphinxafterbreak}{\char`\;}}%
- \lccode`\~`\:\lowercase{\def~}{\discretionary{\char`\:}{\Sphinxafterbreak}{\char`\:}}%
- \lccode`\~`\?\lowercase{\def~}{\discretionary{\char`\?}{\Sphinxafterbreak}{\char`\?}}%
- \lccode`\~`\!\lowercase{\def~}{\discretionary{\char`\!}{\Sphinxafterbreak}{\char`\!}}%
- \lccode`\~`\/\lowercase{\def~}{\discretionary{\char`\/}{\Sphinxafterbreak}{\char`\/}}%
+\newcommand*\sphinxbreaksatpunct {%
+ \lccode`\~`\.\lowercase{\def~}{\discretionary{\char`\.}{\sphinxafterbreak}{\char`\.}}%
+ \lccode`\~`\,\lowercase{\def~}{\discretionary{\char`\,}{\sphinxafterbreak}{\char`\,}}%
+ \lccode`\~`\;\lowercase{\def~}{\discretionary{\char`\;}{\sphinxafterbreak}{\char`\;}}%
+ \lccode`\~`\:\lowercase{\def~}{\discretionary{\char`\:}{\sphinxafterbreak}{\char`\:}}%
+ \lccode`\~`\?\lowercase{\def~}{\discretionary{\char`\?}{\sphinxafterbreak}{\char`\?}}%
+ \lccode`\~`\!\lowercase{\def~}{\discretionary{\char`\!}{\sphinxafterbreak}{\char`\!}}%
+ \lccode`\~`\/\lowercase{\def~}{\discretionary{\char`\/}{\sphinxafterbreak}{\char`\/}}%
\catcode`\.\active
\catcode`\,\active
\catcode`\;\active
@@ -272,42 +311,55 @@
\lccode`\~`\~
}
-\renewcommand{\Verbatim}[1][1]{%
+% needed to create wrapper environments of fancyvrb's Verbatim
+\newcommand*{\sphinxVerbatimEnvironment}{\gdef\FV@EnvironName{sphinxVerbatim}}
+% Sphinx <1.5 optional argument was in fact mandatory. It is now really
+% optional and handled by original Verbatim.
+\newenvironment{sphinxVerbatim}{%
% quit horizontal mode if we are still in a paragraph
\par
% list starts new par, but we don't want it to be set apart vertically
\parskip\z@skip
% first, let's check if there is a caption
- \ifx\SphinxVerbatimTitle\empty
+ \ifx\sphinxVerbatimTitle\empty
\addvspace\z@% counteract possible previous negative skip (French lists!)
\smallskip
% there was no caption. Check if nevertheless a label was set.
- \ifx\SphinxLiteralBlockLabel\empty\else
+ \ifx\sphinxLiteralBlockLabel\empty\else
% we require some space to be sure hyperlink target from \phantomsection
% will not be separated from upcoming verbatim by a page break
- \needspace{\literalblockwithoutcaptionneedspace}%
- \phantomsection\SphinxLiteralBlockLabel
+ \needspace{\sphinxliteralblockwithoutcaptionneedspace}%
+ \phantomsection\sphinxLiteralBlockLabel
\fi
+ \setbox\spx@VerbatimTitleBox\box\voidb@x
+ \else
+ % non-empty \sphinxVerbatimTitle has label inside it (in case there is one)
+ \setbox\spx@VerbatimTitleBox
+ \hbox{\begin{minipage}{\linewidth}%
+ \sphinxVerbatimTitle
+ \end{minipage}}%
\fi
- % non-empty \SphinxVerbatimTitle has label inside it (in case there is one)
+ \fboxsep\sphinxverbatimsep \fboxrule\sphinxverbatimborder
+ % setting borderwidth to zero is simplest for no-frame effect with same pagebreaks
+ \ifsphinxverbatimwithframe\else\fboxrule\z@\fi
% Customize framed.sty \MakeFramed to glue caption to literal block
- \global\Sphinx@myfirstframedpasstrue
- % via \Sphinx@fcolorbox, will use \Sphinx@VerbatimFBox which inserts title
- \def\FrameCommand {\Sphinx@colorbox\Sphinx@fcolorbox }%
+ % via \spx@fcolorbox, will use \spx@VerbatimFBox which inserts title
+ \def\FrameCommand {\spx@colorbox\spx@fcolorbox }%
\let\FirstFrameCommand\FrameCommand
% for mid pages and last page portion of (long) split frame:
- \def\MidFrameCommand{\Sphinx@colorbox\fcolorbox }%
+ \def\MidFrameCommand{\spx@colorbox\fcolorbox }%
\let\LastFrameCommand\MidFrameCommand
+ \ifsphinxverbatimwrapslines
% fancyvrb's Verbatim puts each input line in (unbreakable) horizontal boxes.
% This customization wraps each line from the input in a \vtop, thus
% allowing it to wrap and display on two or more lines in the latex output.
% - The codeline counter will be increased only once.
% - The wrapped material will not break across pages, it is impossible
% to achieve this without extensive rewrite of fancyvrb.
- % - The (not used in Sphinx) obeytabs option to Verbatim is
+ % - The (not used in sphinx) obeytabs option to Verbatim is
% broken by this change (showtabs and tabspace work).
- \sbox\Sphinxcontinuationbox {\Sphinxcontinuationsymbol}%
- \sbox\Sphinxvisiblespacebox {\FV@SetupFont\Sphinxvisiblespace}%
+ \sbox\sphinxcontinuationbox {\sphinxcontinuationsymbol}%
+ \sbox\sphinxvisiblespacebox {\FV@SetupFont\sphinxvisiblespace}%
\def\FancyVerbFormatLine ##1{\hsize\linewidth
\vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@
\doublehyphendemerits\z@\finalhyphendemerits\z@
@@ -318,74 +370,100 @@
% Stretch/shrink are however usually zero for typewriter font.
\def\FV@Space {%
\nobreak\hskip\z@ plus\fontdimen3\font minus\fontdimen4\font
- \discretionary{\copy\Sphinxvisiblespacebox}{\Sphinxafterbreak}
+ \discretionary{\copy\sphinxvisiblespacebox}{\sphinxafterbreak}
{\kern\fontdimen2\font}%
}%
% Allow breaks at special characters using \PYG... macros.
- \Sphinxbreaksatspecials
+ \sphinxbreaksatspecials
+ % Breaks at punctuation characters . , ; ? ! and / (needs catcode activation)
+ \def\FancyVerbCodes{\sphinxbreaksatpunct}%
+ \fi % end of conditional code for wrapping long code lines
+ % go around fancyvrb's check of \@currenvir
+ \let\VerbatimEnvironment\sphinxVerbatimEnvironment
+ % go around fancyvrb's check of current list depth
+ \def\@toodeep {\advance\@listdepth\@ne}%
% The list environment is needed to control perfectly the vertical space.
% Note: \OuterFrameSep used by framed.sty is later set to \topsep hence 0pt.
% - if caption: vertical space above caption = (\abovecaptionskip + D) with
% D = \baselineskip-\FrameHeightAdjust, and then \smallskip above frame.
% - if no caption: (\smallskip + D) above frame. By default D=6pt.
- \list{}{%
- \setlength\parskip{0pt}%
- \setlength\itemsep{0ex}%
- \setlength\topsep{0ex}%
- \setlength\parsep{0pt}% let's not forget this one!
- \setlength\partopsep{0pt}%
- \setlength\leftmargin{0pt}%
- }%
- \item
- % use a minipage if we are already inside a framed environment
- \relax\ifSphinx@inframed\noindent\begin{\minipage}{\linewidth}\fi
+ % Use trivlist rather than list to avoid possible "too deeply nested" error.
+ \itemsep \z@skip
+ \topsep \z@skip
+ \partopsep \z@skip% trivlist will set \parsep to \parskip = zero (see above)
+ % \leftmargin will be set to zero by trivlist
+ \rightmargin\z@
+ \parindent \z@% becomes \itemindent. Default zero, but perhaps overwritten.
+ \trivlist\item\relax
+ \ifsphinxverbatimwithminipage\spx@inframedtrue\fi
+ % use a minipage if we are already inside a framed environment
+ \ifspx@inframed\noindent\begin{minipage}{\linewidth}\fi
\MakeFramed {% adapted over from framed.sty's snugshade environment
- \advance\hsize-\width\@totalleftmargin\z@\linewidth\hsize
- \@setminipage }%
- \small
+ \advance\hsize-\width\@totalleftmargin\z@\linewidth\hsize\@setminipage
+ }%
% For grid placement from \strut's in \FancyVerbFormatLine
\lineskip\z@skip
- % Breaks at punctuation characters . , ; ? ! and / need catcode=\active
- \OriginalVerbatim[#1,codes*=\Sphinxbreaksatpunct]%
+ % will fetch its optional arguments if any
+ \OriginalVerbatim
}
-\renewcommand{\endVerbatim}{%
+{%
\endOriginalVerbatim
- \par\unskip\@minipagefalse\endMakeFramed
- \ifSphinx@inframed\end{minipage}\fi
- \endlist
- % LaTeX environments always revert local changes on exit, here e.g. \parskip
+ \par\unskip\@minipagefalse\endMakeFramed % from framed.sty snugshade
+ \ifspx@inframed\end{minipage}\fi
+ \endtrivlist
}
+\newenvironment {sphinxVerbatimNoFrame}
+ {\sphinxverbatimwithframefalse
+ % needed for fancyvrb as literal code will end in \end{sphinxVerbatimNoFrame}
+ \def\sphinxVerbatimEnvironment{\gdef\FV@EnvironName{sphinxVerbatimNoFrame}}%
+ \begin{sphinxVerbatim}}
+ {\end{sphinxVerbatim}}
+\newenvironment {sphinxVerbatimintable}
+ {% don't use a frame if in a table cell
+ \sphinxverbatimwithframefalse
+ \sphinxverbatimwithminipagetrue
+ % counteract longtable redefinition of caption
+ \let\caption\sphinxfigcaption
+ % reduce above caption space if in a table cell
+ \abovecaptionskip\smallskipamount
+ \def\sphinxVerbatimEnvironment{\gdef\FV@EnvironName{sphinxVerbatimintable}}%
+ \begin{sphinxVerbatim}}
+ {\end{sphinxVerbatim}}
% define macro to frame contents and add shadow on right and bottom
-\def\Sphinx@shadowsep {5\p@} % \p@ means "pt "
-\def\Sphinx@shadowsize {4\p@}
-\def\Sphinx@shadowrule {\fboxrule}
-\long\def\Sphinx@ShadowFBox#1{%
+% use public names for customizable lengths
+\newlength\sphinxshadowsep \setlength\sphinxshadowsep {5pt}
+\newlength\sphinxshadowsize \setlength\sphinxshadowsize {4pt}
+\newlength\sphinxshadowrule
+% this uses \fboxrule value at loading time of sphinx.sty (0.4pt normally)
+\setlength\sphinxshadowrule {\fboxrule}
+
+\long\def\spx@ShadowFBox#1{%
\leavevmode\begingroup
% first we frame the box #1
\setbox\@tempboxa
- \hbox{\vrule\@width\Sphinx@shadowrule
- \vbox{\hrule\@height\Sphinx@shadowrule
- \kern\Sphinx@shadowsep
- \hbox{\kern\Sphinx@shadowsep #1\kern\Sphinx@shadowsep}%
- \kern\Sphinx@shadowsep
- \hrule\@height\Sphinx@shadowrule}%
- \vrule\@width\Sphinx@shadowrule}%
+ \hbox{\vrule\@width\sphinxshadowrule
+ \vbox{\hrule\@height\sphinxshadowrule
+ \kern\sphinxshadowsep
+ \hbox{\kern\sphinxshadowsep #1\kern\sphinxshadowsep}%
+ \kern\sphinxshadowsep
+ \hrule\@height\sphinxshadowrule}%
+ \vrule\@width\sphinxshadowrule}%
% Now we add the shadow, like \shadowbox from fancybox.sty would do
- \dimen@\dimexpr.5\Sphinx@shadowrule+\Sphinx@shadowsize\relax
+ \dimen@\dimexpr.5\sphinxshadowrule+\sphinxshadowsize\relax
\hbox{\vbox{\offinterlineskip
- \hbox{\copy\@tempboxa\kern-.5\Sphinx@shadowrule
+ \hbox{\copy\@tempboxa\kern-.5\sphinxshadowrule
% add shadow on right side
- \lower\Sphinx@shadowsize
+ \lower\sphinxshadowsize
\hbox{\vrule\@height\ht\@tempboxa \@width\dimen@}%
}%
\kern-\dimen@ % shift back vertically to bottom of frame
% and add shadow at bottom
- \moveright\Sphinx@shadowsize
+ \moveright\sphinxshadowsize
\vbox{\hrule\@width\wd\@tempboxa \@height\dimen@}%
}%
% move left by the size of right shadow so shadow adds no width
- \kern-\Sphinx@shadowsize
+ \kern-\sphinxshadowsize
}%
\endgroup
}
@@ -394,10 +472,10 @@
% works well inside Lists and Quote-like environments
% produced by ``topic'' directive (or local contents)
% could nest if LaTeX writer authorized it
-\newenvironment{SphinxShadowBox}
- {\def\FrameCommand {\Sphinx@ShadowFBox }%
+\newenvironment{sphinxShadowBox}
+ {\def\FrameCommand {\spx@ShadowFBox }%
% configure framed.sty not to add extra vertical spacing
- \OuterFrameSep \z@skip
+ \spx@ifundefined{OuterFrameSep}{}{\OuterFrameSep\z@skip}%
% the \trivlist will add the vertical spacing on top and bottom which is
% typical of center environment as used in Sphinx <= 1.4.1
% the \noindent has the effet of an extra blank line on top, to
@@ -406,8 +484,8 @@
\def\FrameHeightAdjust {\baselineskip}%
\trivlist\item\noindent
% use a minipage if we are already inside a framed environment
- \ifSphinx@inframed\begin{minipage}{\linewidth}\fi
- \MakeFramed {\Sphinx@inframedtrue
+ \ifspx@inframed\begin{minipage}{\linewidth}\fi
+ \MakeFramed {\spx@inframedtrue
% framed.sty puts into "\width" the added width (=2shadowsep+2shadowrule)
% adjust \hsize to what the contents must use
\advance\hsize-\width
@@ -433,7 +511,7 @@
\fi
\@minipagefalse
\endMakeFramed
- \ifSphinx@inframed\end{minipage}\fi
+ \ifspx@inframed\end{minipage}\fi
\endtrivlist
}
@@ -474,25 +552,25 @@
}{\end{list}}
% \optional is used for ``[, arg]``, i.e. desc_optional nodes.
-\newcommand{\optional}[1]{%
+\newcommand{\sphinxoptional}[1]{%
{\textnormal{\Large[}}{#1}\hspace{0.5mm}{\textnormal{\Large]}}}
\newlength{\py@argswidth}
\newcommand{\py@sigparams}[2]{%
- \parbox[t]{\py@argswidth}{#1\code{)}#2}}
+ \parbox[t]{\py@argswidth}{#1\sphinxcode{)}#2}}
\newcommand{\pysigline}[1]{\item[#1]\nopagebreak}
\newcommand{\pysiglinewithargsret}[3]{%
- \settowidth{\py@argswidth}{#1\code{(}}%
+ \settowidth{\py@argswidth}{#1\sphinxcode{(}}%
\addtolength{\py@argswidth}{-2\py@argswidth}%
\addtolength{\py@argswidth}{\linewidth}%
- \item[#1\code{(}\py@sigparams{#2}{#3}]}
+ \item[#1\sphinxcode{(}\py@sigparams{#2}{#3}]}
% Production lists
%
\newenvironment{productionlist}{
-% \def\optional##1{{\Large[}##1{\Large]}}
- \def\production##1##2{\\\code{##1}&::=&\code{##2}}
- \def\productioncont##1{\\& &\code{##1}}
+% \def\sphinxoptional##1{{\Large[}##1{\Large]}}
+ \def\production##1##2{\\\sphinxcode{##1}&::=&\sphinxcode{##2}}
+ \def\productioncont##1{\\& &\sphinxcode{##1}}
\parindent=2em
\indent
\setlength{\LTpre}{0pt}
@@ -503,29 +581,79 @@
}
% Notices / Admonitions
-%
+% Some are quite plain
+\newenvironment{sphinxlightbox}{%
+ \par\allowbreak
+ \noindent{\color{spx@notice@bordercolor}%
+ \rule{\linewidth}{\spx@notice@border}}\par\nobreak
+ {\parskip\z@skip\noindent}%
+ }
+ {%
+ \par
+ % counteract previous possible negative skip (French lists!):
+ % (we can't cancel that any earlier \vskip introduced a potential pagebreak)
+ \ifdim\lastskip<\z@\vskip-\lastskip\fi
+ \nobreak\vbox{\noindent\kern\@totalleftmargin
+ {\color{spx@notice@bordercolor}%
+ \rule[\dimexpr.4\baselineskip-\spx@notice@border\relax]
+ {\linewidth}{\spx@notice@border}}\hss}\allowbreak
+ }% end of sphinxlightbox environment definition
+% may be renewenvironment'd by user for complete customization
+\newenvironment{sphinxnote}[1]
+ {\begin{sphinxlightbox}\sphinxstrong{#1} }{\end{sphinxlightbox}}
+\newenvironment{sphinxhint}[1]
+ {\begin{sphinxlightbox}\sphinxstrong{#1} }{\end{sphinxlightbox}}
+\newenvironment{sphinximportant}[1]
+ {\begin{sphinxlightbox}\sphinxstrong{#1} }{\end{sphinxlightbox}}
+\newenvironment{sphinxtip}[1]
+ {\begin{sphinxlightbox}\sphinxstrong{#1} }{\end{sphinxlightbox}}
+% or user may just customize the bordercolor and the border width
+% re-use \definecolor if change needed, and \renewcommand for rule width
+\definecolor{sphinxnotebordercolor}{rgb}{0,0,0}
+\definecolor{sphinxhintbordercolor}{rgb}{0,0,0}
+\definecolor{sphinximportantbordercolor}{rgb}{0,0,0}
+\definecolor{sphinxtipbordercolor}{rgb}{0,0,0}
+\newcommand{\sphinxnoteborder}{0.5pt}
+\newcommand{\sphinxhintborder}{0.5pt}
+\newcommand{\sphinximportantborder}{0.5pt}
+\newcommand{\sphinxtipborder}{0.5pt}
+% these are needed for common handling by notice environment of lightbox
+% and heavybox but they are currently not used by lightbox environment
+\definecolor{sphinxnotebgcolor}{rgb}{1,1,1}
+\definecolor{sphinxhintbgcolor}{rgb}{1,1,1}
+\definecolor{sphinximportantbgcolor}{rgb}{1,1,1}
+\definecolor{sphinxtipbgcolor}{rgb}{1,1,1}
+
+% Others get more distinction
+\newdimen\spx@notice@border
% Code adapted from framed.sty's "snugshade" environment.
% Nesting works (inner frames do not allow page breaks).
-\newcommand{\py@heavybox}{\par
- \setlength{\FrameRule}{\p@}% 1pt
+\newenvironment{sphinxheavybox}{\par
+ \setlength{\FrameRule}{\spx@notice@border}%
\setlength{\FrameSep}{\dimexpr.6\baselineskip-\FrameRule\relax}
% configure framed.sty's parameters to obtain same vertical spacing
% as for "light" boxes. We need for this to manually insert parskip glue and
% revert a skip done by framed before the frame.
- \setlength{\OuterFrameSep}{0pt}
+ \spx@ifundefined{OuterFrameSep}{}{\OuterFrameSep\z@skip}%
\vspace{\FrameHeightAdjust}
% copied/adapted from framed.sty's snugshade
\def\FrameCommand##1{\hskip\@totalleftmargin
- \fboxsep\FrameSep \fboxrule\FrameRule\fbox{##1}%
+ \fboxsep\FrameSep \fboxrule\FrameRule
+ \fcolorbox{spx@notice@bordercolor}{spx@notice@bgcolor}{##1}%
\hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth}%
% use a minipage if we are already inside a framed environment
- \ifSphinx@inframed
+ \ifspx@inframed
\noindent\begin{minipage}{\linewidth}
\else
- \vspace{\parskip}
+ % handle case where notice is first thing in a list item (or is quoted)
+ \if@inlabel
+ \noindent\par\vspace{-\baselineskip}
+ \else
+ \vspace{\parskip}
+ \fi
\fi
- \MakeFramed {\Sphinx@inframedtrue
+ \MakeFramed {\spx@inframedtrue
\advance\hsize-\width \@totalleftmargin\z@ \linewidth\hsize
% minipage initialization copied from LaTeX source code.
\@pboxswfalse
@@ -536,58 +664,66 @@
\@minipagerestore
\@setminipage }%
}
-\newcommand{\py@endheavybox}{%
+ {%
\par\unskip
% handles footnotes
\ifvoid\@mpfootins\else
\vskip\skip\@mpfootins\normalcolor\footnoterule\unvbox\@mpfootins
\fi
- \@minipagefalse\endMakeFramed
- \ifSphinx@inframed\end{minipage}\fi
+ \@minipagefalse
+ \endMakeFramed
+ \ifspx@inframed\end{minipage}\fi
% arrange for similar spacing below frame as for "light" boxes.
\vskip .4\baselineskip
- }
-
-\newcommand{\py@lightbox}{%
- \par\allowbreak
- \noindent\rule{\linewidth}{0.5pt}\par\nobreak
- {\parskip\z@skip\noindent}%
- }
-\newcommand{\py@endlightbox}{%
- \par
- % counteract previous possible negative skip (French lists!):
- % (we can't cancel that any earlier \vskip introduced a potential pagebreak)
- \ifdim\lastskip<\z@\vskip-\lastskip\fi
- \nobreak\vbox{\noindent\rule[.4\baselineskip]{\linewidth}{0.5pt}}\allowbreak
- }
-
-% Some are quite plain:
-\newcommand{\py@noticestart@note}{\py@lightbox}
-\newcommand{\py@noticeend@note}{\py@endlightbox}
-\newcommand{\py@noticestart@hint}{\py@lightbox}
-\newcommand{\py@noticeend@hint}{\py@endlightbox}
-\newcommand{\py@noticestart@important}{\py@lightbox}
-\newcommand{\py@noticeend@important}{\py@endlightbox}
-\newcommand{\py@noticestart@tip}{\py@lightbox}
-\newcommand{\py@noticeend@tip}{\py@endlightbox}
-
-% Others gets more visible distinction:
-\newcommand{\py@noticestart@warning}{\py@heavybox}
-\newcommand{\py@noticeend@warning}{\py@endheavybox}
-\newcommand{\py@noticestart@caution}{\py@heavybox}
-\newcommand{\py@noticeend@caution}{\py@endheavybox}
-\newcommand{\py@noticestart@attention}{\py@heavybox}
-\newcommand{\py@noticeend@attention}{\py@endheavybox}
-\newcommand{\py@noticestart@danger}{\py@heavybox}
-\newcommand{\py@noticeend@danger}{\py@endheavybox}
-\newcommand{\py@noticestart@error}{\py@heavybox}
-\newcommand{\py@noticeend@error}{\py@endheavybox}
-
-\newenvironment{notice}[2]{
- \def\py@noticetype{#1}
- \csname py@noticestart@#1\endcsname
- \strong{#2}
-}{\csname py@noticeend@\py@noticetype\endcsname}
+ }% end of sphinxheavybox environment definition
+% may be renewenvironment'd by user for complete customization
+\newenvironment{sphinxwarning}[1]
+ {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}}
+\newenvironment{sphinxcaution}[1]
+ {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}}
+\newenvironment{sphinxattention}[1]
+ {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}}
+\newenvironment{sphinxdanger}[1]
+ {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}}
+\newenvironment{sphinxerror}[1]
+ {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}}
+% or just re-do \definecolor for colours, \renewcommand for frame width
+\definecolor{sphinxwarningbordercolor}{rgb}{0,0,0}
+\definecolor{sphinxcautionbordercolor}{rgb}{0,0,0}
+\definecolor{sphinxattentionbordercolor}{rgb}{0,0,0}
+\definecolor{sphinxdangerbordercolor}{rgb}{0,0,0}
+\definecolor{sphinxerrorbordercolor}{rgb}{0,0,0}
+\definecolor{sphinxwarningbgcolor}{rgb}{1,1,1}
+\definecolor{sphinxcautionbgcolor}{rgb}{1,1,1}
+\definecolor{sphinxattentionbgcolor}{rgb}{1,1,1}
+\definecolor{sphinxdangerbgcolor}{rgb}{1,1,1}
+\definecolor{sphinxerrorbgcolor}{rgb}{1,1,1}
+\newcommand{\sphinxwarningborder}{1pt}
+\newcommand{\sphinxcautionborder}{1pt}
+\newcommand{\sphinxattentionborder}{1pt}
+\newcommand{\sphinxdangerborder}{1pt}
+\newcommand{\sphinxerrorborder}{1pt}
+
+% the \colorlet of xcolor (if at all loaded) is overkill for our use case
+\newcommand{\sphinxcolorlet}[2]
+ {\expandafter\let\csname\@backslashchar color@#1\expandafter\endcsname
+ \csname\@backslashchar color@#2\endcsname }
+
+% the main dispatch for all types of notices
+\newenvironment{sphinxadmonition}{\begin{notice}}{\end{notice}}
+% use of ``notice'' is for backwards compatibility and will be removed in
+% future release; sphinxadmonition environment will be defined directly.
+\newenvironment{notice}[2]{% #1=type, #2=heading
+ % can't use #1 directly in definition of end part
+ \def\spx@noticetype {#1}%
+ % set parameters of heavybox/lightbox
+ \sphinxcolorlet{spx@notice@bordercolor}{sphinx#1bordercolor}%
+ \sphinxcolorlet{spx@notice@bgcolor}{sphinx#1bgcolor}%
+ \setlength\spx@notice@border {\dimexpr\csname sphinx#1border\endcsname\relax}%
+ % start specific environment, passing the heading as argument
+ \begin{sphinx#1}{#2}}
+ % in end part, need to go around a LaTeX's "feature"
+ {\edef\spx@temp{\noexpand\end{sphinx\spx@noticetype}}\spx@temp}
% Allow the release number to be specified independently of the
% \date{}. This allows the date to reflect the document's date and
@@ -616,7 +752,7 @@
% This sets up the fancy chapter headings that make the documents look
% at least a little better than the usual LaTeX output.
%
-\@ifundefined{ChTitleVar}{}{
+\spx@ifundefined{ChTitleVar}{}{
\ChNameVar{\raggedleft\normalsize\py@HeaderFamily}
\ChNumVar{\raggedleft \bfseries\Large\py@HeaderFamily}
\ChTitleVar{\raggedleft \textrm{\Huge\py@HeaderFamily}}
@@ -656,7 +792,7 @@
% The following is stuff copied from docutils' latex writer.
%
-\newcommand{\optionlistlabel}[1]{\bf #1 \hfill}
+\newcommand{\optionlistlabel}[1]{\normalfont\bfseries #1 \hfill}% \bf deprecated
\newenvironment{optionlist}[1]
{\begin{list}{}
{\setlength{\labelwidth}{#1}
@@ -678,26 +814,29 @@
\raggedright}
{\end{list}}
-% Redefine includgraphics for avoiding images larger than the screen size
-% If the size is not specified.
+% Re-define \includegraphics to resize images larger than the line width
+% if the size is not specified.
+% Warning: future version of Sphinx will not modify original \includegraphics,
+% Below custom code will be direct definition of \sphinxincludegraphics, with
+% \py@Oldincludegraphics replaced by direct use of original \includegraphics.
\let\py@Oldincludegraphics\includegraphics
-
-\newbox\image@box%
-\newdimen\image@width%
-\renewcommand\includegraphics[2][\@empty]{%
- \ifx#1\@empty%
- \setbox\image@box=\hbox{\py@Oldincludegraphics{#2}}%
- \image@width\wd\image@box%
- \ifdim \image@width>\linewidth%
- \setbox\image@box=\hbox{\py@Oldincludegraphics[width=\linewidth]{#2}}%
- \box\image@box%
- \else%
- \py@Oldincludegraphics{#2}%
- \fi%
- \else%
+\newbox\spx@image@box
+\renewcommand*{\includegraphics}[2][\@empty]{%
+ \ifx\@empty #1% attention, #1 could be bb.., bad if first after \ifx
+ \setbox\spx@image@box=\hbox{\py@Oldincludegraphics{#2}}%
+ \ifdim \wd\spx@image@box>\linewidth
+ \py@Oldincludegraphics[width=\linewidth]{#2}%
+ \else
+ \leavevmode\box\spx@image@box
+ \fi
+ \else
\py@Oldincludegraphics[#1]{#2}%
- \fi%
+ \fi
}
+% Writer will put \sphinxincludegraphics in LaTeX source, and with this,
+% documents which used their own modified \includegraphics will compile
+% as before. But see warning above.
+\newcommand*{\sphinxincludegraphics}{\includegraphics}
% to make pdf with correct encoded bookmarks in Japanese
% this should precede the hyperref package
@@ -745,12 +884,12 @@
\fi%
}
-\providecommand*{\DUprovidelength}[2]{
- \ifthenelse{\isundefined{#1}}{\newlength{#1}\setlength{#1}{#2}}{}
+\providecommand*{\DUprovidelength}[2]{%
+ \ifdefined#1\else\newlength{#1}\setlength{#1}{#2}\fi
}
\DUprovidelength{\DUlineblockindent}{2.5em}
-\ifthenelse{\isundefined{\DUlineblock}}{
+\ifdefined\DUlineblock\else
\newenvironment{DUlineblock}[1]{%
\list{}{\setlength{\partopsep}{\parskip}
\addtolength{\partopsep}{\baselineskip}
@@ -761,8 +900,7 @@
\raggedright
}
{\endlist}
-}{}
-
+\fi
% From footmisc.sty: allows footnotes in titles
\let\FN@sf@@footnote\footnote
@@ -813,18 +951,79 @@
}
\fi
-% Define literal-block environment
-\RequirePackage{newfloat}
-\DeclareFloatingEnvironment{literal-block}
-\ifx\thechapter\undefined
- \SetupFloatingEnvironment{literal-block}{within=section,placement=h}
-\else
- \SetupFloatingEnvironment{literal-block}{within=chapter,placement=h}
-\fi
-\SetupFloatingEnvironment{literal-block}{name=List}
+% for captions of literal blocks
+\newcounter{literalblock}
+\spx@ifundefined{c@chapter}
+ {\@addtoreset{literalblock}{section}
+ \def\theliteralblock {\ifnum\c@section>\z@ \thesection.\fi\arabic{literalblock}}
+ \def\theHliteralblock {\theHsection.\arabic{literalblock}}}
+ {\@addtoreset{literalblock}{chapter}
+ \def\theliteralblock {\ifnum\c@chapter>\z@ \thechapter.\fi\arabic{literalblock}}
+ \def\theHliteralblock {\theHchapter.\arabic{literalblock}}}
+% at start of caption title
+\newcommand*{\fnum@literalblock}{\literalblockname\nobreakspace\theliteralblock}
+% this will be overwritten in document preamble by Babel translation
+\newcommand*{\literalblockname}{Listing }
+% file extension needed for \caption's good functioning, the file is created
+% only if a \listof{literalblock}{foo} command is encountered, which is
+% analogous to \listoffigures, but for the code listings (foo = chosen title.)
+\newcommand*{\ext@literalblock}{lol}
+
% control caption around literal-block
\RequirePackage{capt-of}
\RequirePackage{needspace}
% if the left page space is less than \literalblockneedspace, insert page-break
-\newcommand{\literalblockneedspace}{5\baselineskip}
-\newcommand{\literalblockwithoutcaptionneedspace}{1.5\baselineskip}
+\newcommand{\sphinxliteralblockneedspace}{5\baselineskip}
+\newcommand{\sphinxliteralblockwithoutcaptionneedspace}{1.5\baselineskip}
+
+% figure in table
+\newenvironment{sphinxfigure-in-table}[1][\linewidth]{%
+ \def\@captype{figure}%
+ \begin{minipage}{#1}%
+}{\end{minipage}}
+% store original \caption macro for use with figures in longtable and tabulary
+\AtBeginDocument{\let\spx@originalcaption\caption}
+\newcommand*\sphinxfigcaption
+ {\ifx\equation$%$% this is trick to identify tabulary first pass
+ \firstchoice@false\else\firstchoice@true\fi
+ \spx@originalcaption }
+
+% by default, also define macros with the no-prefix names
+\ifsphinxKeepOldNames
+ \typeout{** (sphinx) defining (legacy) text style macros without \string\sphinx\space prefix}
+ \typeout{** if clashes with packages, set latex_keep_old_macro_names=False in conf.py}
+ \@for\@tempa:=strong,bfcode,email,tablecontinued,titleref,%
+ menuselection,accelerator,crossref,termref,optional\do
+{% first, check if command with no prefix already exists
+ \expandafter\newcommand\csname\@tempa\endcsname{}%
+ % if no error give it the meaning defined so far with \sphinx prefix
+ \expandafter\let\csname\@tempa\expandafter\endcsname
+ \csname sphinx\@tempa\endcsname
+ % redefine the \sphinx prefixed macro to expand to non-prefixed one
+ \expandafter\def\csname sphinx\@tempa\expandafter\endcsname
+ \expandafter{\csname\@tempa\endcsname}%
+}
+ % robustified case needs special treatment
+ \newcommand\code{}\let\code\relax
+ \DeclareRobustCommand{\code}[1]{{\@noligs\scantokens{\texttt{#1}\relax}}}
+ \def\sphinxcode{\code}%
+\fi
+
+% additional customizable styling
+\newcommand*{\sphinxstyleindexentry}{\texttt}
+\newcommand{\sphinxstyleindexextra}[1]{ \emph{(#1)}}
+\newcommand*{\sphinxstyleindexpageref}{, \pageref}
+\newcommand{\sphinxstyletopictitle}[1]{\textbf{#1}\par\medskip}
+\let\sphinxstylesidebartitle\sphinxstyletopictitle
+\newcommand*{\sphinxstyleothertitle}{\textbf}
+\newcommand{\sphinxstylesidebarsubtitle}[1]{~\\\textbf{#1} \smallskip}
+\newcommand*{\sphinxstylethead}{\textsf}
+\newcommand*{\sphinxstyleemphasis}{\emph}
+\newcommand{\sphinxstyleliteralemphasis}[1]{\emph{\texttt{#1}}}
+\newcommand*{\sphinxstylestrong}{\textbf}
+\newcommand{\sphinxstyleliteralstrong}[1]{\textbf{\texttt{#1}}}
+\newcommand*{\sphinxstyleabbreviation}{\textsc}
+\newcommand*{\sphinxstyleliteralintitle}{\texttt}
+
+% stylesheet for highlighting with pygments
+\RequirePackage{sphinxhighlight}
diff --git a/sphinx/texinputs/sphinxhowto.cls b/sphinx/texinputs/sphinxhowto.cls
index 8607ef8c4..8d5c59232 100644
--- a/sphinx/texinputs/sphinxhowto.cls
+++ b/sphinx/texinputs/sphinxhowto.cls
@@ -35,30 +35,31 @@
% Change the title page to look a bit better, and fit in with the fncychap
% ``Bjarne'' style a bit better.
%
-\renewcommand{\maketitle}{
- \rule{\textwidth}{1pt}
+\renewcommand{\maketitle}{%
+ \noindent\rule{\textwidth}{1pt}\ifsphinxpdfoutput\newline\null\fi\par
\ifsphinxpdfoutput
\begingroup
% These \defs are required to deal with multi-line authors; it
% changes \\ to ', ' (comma-space), making it pass muster for
% generating document info in the PDF file.
- \def\\{, }
- \def\and{and }
+ \def\\{, }%
+ \def\and{and }%
\pdfinfo{
/Author (\@author)
/Title (\@title)
- }
+ }%
\endgroup
\fi
\begin{flushright}
- \sphinxlogo%
- {\rm\Huge\py@HeaderFamily \@title} \par
- {\em\large\py@HeaderFamily \py@release\releaseinfo} \par
+ \sphinxlogo
+ \py@HeaderFamily
+ {\Huge \@title }\par
+ {\itshape\large \py@release \releaseinfo}\par
\vspace{25pt}
- {\Large\py@HeaderFamily
+ {\Large
\begin{tabular}[t]{c}
\@author
- \end{tabular}} \par
+ \end{tabular}}\par
\vspace{25pt}
\@date \par
\py@authoraddress \par
diff --git a/sphinx/texinputs/sphinxmanual.cls b/sphinx/texinputs/sphinxmanual.cls
index b576b673e..f20449449 100644
--- a/sphinx/texinputs/sphinxmanual.cls
+++ b/sphinx/texinputs/sphinxmanual.cls
@@ -43,26 +43,27 @@
\begin{titlepage}%
\let\footnotesize\small
\let\footnoterule\relax
- \rule{\textwidth}{1pt}%
+ \noindent\rule{\textwidth}{1pt}\ifsphinxpdfoutput\newline\null\fi\par
\ifsphinxpdfoutput
\begingroup
% These \defs are required to deal with multi-line authors; it
% changes \\ to ', ' (comma-space), making it pass muster for
% generating document info in the PDF file.
- \def\\{, }
- \def\and{and }
+ \def\\{, }%
+ \def\and{and }%
\pdfinfo{
/Author (\@author)
/Title (\@title)
- }
+ }%
\endgroup
\fi
\begin{flushright}%
- \sphinxlogo%
- {\rm\Huge\py@HeaderFamily \@title \par}%
- {\em\LARGE\py@HeaderFamily \py@release\releaseinfo \par}
+ \sphinxlogo
+ \py@HeaderFamily
+ {\Huge \@title \par}
+ {\itshape\LARGE \py@release\releaseinfo \par}
\vfill
- {\LARGE\py@HeaderFamily
+ {\LARGE
\begin{tabular}[t]{c}
\@author
\end{tabular}
@@ -76,52 +77,27 @@
\end{flushright}%\par
\@thanks
\end{titlepage}%
- \cleardoublepage%
\setcounter{footnote}{0}%
\let\thanks\relax\let\maketitle\relax
%\gdef\@thanks{}\gdef\@author{}\gdef\@title{}
}
-
-% Catch the end of the {abstract} environment, but here make sure the abstract
-% is followed by a blank page if the 'openright' option is used.
-%
-\let\py@OldEndAbstract=\endabstract
-\renewcommand{\endabstract}{
- \if@openright
- \ifodd\value{page}
- \typeout{Adding blank page after the abstract.}
- \vfil\pagebreak
- \fi
- \fi
- \py@OldEndAbstract
-}
-
-% This wraps the \tableofcontents macro with all the magic to get the spacing
-% right and have the right number of pages if the 'openright' option has been
-% used. This eliminates a fair amount of crud in the individual document files.
-%
\let\py@OldTableofcontents=\tableofcontents
\renewcommand{\tableofcontents}{%
+ % before resetting page counter, let's do the right thing.
+ \if@openright\cleardoublepage\else\clearpage\fi
\pagenumbering{roman}%
- \setcounter{page}{1}%
- \pagebreak%
\pagestyle{plain}%
- {%
- \parskip = 0mm%
- \py@OldTableofcontents%
- \if@openright%
- \ifodd\value{page}%
- \typeout{Adding blank page after the table of contents.}%
- \pagebreak\hspace{0pt}%
- \fi%
- \fi%
- \cleardoublepage%
- }%
+ \begingroup
+ \parskip \z@skip
+ \py@OldTableofcontents
+ \endgroup
+ % before resetting page counter, let's do the right thing.
+ \if@openright\cleardoublepage\else\clearpage\fi
\pagenumbering{arabic}%
- \@ifundefined{fancyhf}{}{\pagestyle{normal}}%
+ \ifdefined\fancyhf\pagestyle{normal}\fi
}
-\pagenumbering{alph}
+\pagenumbering{alph}% avoid hyperref "duplicate destination" warnings
% This is needed to get the width of the section # area wide enough in the
% library reference. Doing it here keeps it the same for all the manuals.
@@ -134,7 +110,7 @@
% For a report document class this environment is a chapter.
\let\py@OldThebibliography=\thebibliography
\renewcommand{\thebibliography}[1]{
- \cleardoublepage
+ \if@openright\cleardoublepage\else\clearpage\fi
\phantomsection
\py@OldThebibliography{1}
\addcontentsline{toc}{chapter}{\bibname}
@@ -146,7 +122,7 @@
\@ifclassloaded{memoir}{}{
\let\py@OldTheindex=\theindex
\renewcommand{\theindex}{
- \cleardoublepage
+ \if@openright\cleardoublepage\else\clearpage\fi
\phantomsection
\py@OldTheindex
\addcontentsline{toc}{chapter}{\indexname}
diff --git a/sphinx/texinputs/tabulary.sty b/sphinx/texinputs/tabulary.sty
index 11fdf7428..03e07ec2a 100644
--- a/sphinx/texinputs/tabulary.sty
+++ b/sphinx/texinputs/tabulary.sty
@@ -14,7 +14,7 @@
%%
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{tabulary}
- [2008/12/01 v0.9 tabulary package (DPC)]
+ [2014/06/11 v0.10 tabulary package (DPC) + footnote patch (sphinx)]
\RequirePackage{array}
\catcode`\Z=14
\DeclareOption{debugshow}{\catcode`\Z=9\relax}
@@ -354,6 +354,7 @@ Z \message{^^JTotal:\the\@tempdima^^J}%
\expandafter\let\expandafter\color\expandafter\relax
\expandafter\let\expandafter\CT@column@color\expandafter\relax
\expandafter\let\expandafter\CT@row@color\expandafter\relax
+ \expandafter\let\expandafter\CT@cell@color\expandafter\relax
\@mkpream{#1}}
\let\TY@@mkpream\@mkpream
\def\TY@classz{%
@@ -396,6 +397,7 @@ Z \message{^^JTotal:\the\@tempdima^^J}%
\CT@setup
\CT@column@color
\CT@row@color
+ \CT@cell@color
\CT@do@color
\endgroup
\@tempdima\ht\z@
diff --git a/sphinx/themes/agogo/static/bgfooter.png b/sphinx/themes/agogo/static/bgfooter.png
index 9ce5bdd90..b7c7cadd4 100644
--- a/sphinx/themes/agogo/static/bgfooter.png
+++ b/sphinx/themes/agogo/static/bgfooter.png
Binary files differ
diff --git a/sphinx/themes/agogo/static/bgtop.png b/sphinx/themes/agogo/static/bgtop.png
index a0d4709ba..05740880f 100644
--- a/sphinx/themes/agogo/static/bgtop.png
+++ b/sphinx/themes/agogo/static/bgtop.png
Binary files differ
diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html
index 1afc4a0bf..f8ff477c7 100644
--- a/sphinx/themes/basic/layout.html
+++ b/sphinx/themes/basic/layout.html
@@ -91,7 +91,8 @@
VERSION: '{{ release|e }}',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
- HAS_SOURCE: {{ has_source|lower }}
+ HAS_SOURCE: {{ has_source|lower }},
+ SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}'
};
</script>
{%- for scriptfile in script_files %}
diff --git a/sphinx/themes/basic/searchbox.html b/sphinx/themes/basic/searchbox.html
index 5749b761f..ae25f7f12 100644
--- a/sphinx/themes/basic/searchbox.html
+++ b/sphinx/themes/basic/searchbox.html
@@ -11,8 +11,8 @@
<div id="searchbox" style="display: none" role="search">
<h3>{{ _('Quick search') }}</h3>
<form class="search" action="{{ pathto('search') }}" method="get">
- <input type="text" name="q" />
- <input type="submit" value="{{ _('Go') }}" />
+ <div><input type="text" name="q" /></div>
+ <div><input type="submit" value="{{ _('Go') }}" /></div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
diff --git a/sphinx/themes/basic/static/basic.css_t b/sphinx/themes/basic/static/basic.css_t
index f6d988e2c..759c43ea5 100644
--- a/sphinx/themes/basic/static/basic.css_t
+++ b/sphinx/themes/basic/static/basic.css_t
@@ -85,10 +85,6 @@ div.sphinxsidebar #searchbox input[type="text"] {
width: 170px;
}
-div.sphinxsidebar #searchbox input[type="submit"] {
- width: 30px;
-}
-
img {
border: 0;
max-width: 100%;
@@ -221,10 +217,6 @@ div.body td {
text-align: left;
}
-.field-list ul {
- padding-left: 1em;
-}
-
.first {
margin-top: 0 !important;
}
@@ -341,10 +333,6 @@ table.docutils td, table.docutils th {
border-bottom: 1px solid #aaa;
}
-table.field-list td, table.field-list th {
- border: 0 !important;
-}
-
table.footnote td, table.footnote th {
border: 0 !important;
}
@@ -381,6 +369,20 @@ div.figure p.caption span.caption-number {
div.figure p.caption span.caption-text {
}
+/* -- field list styles ----------------------------------------------------- */
+
+table.field-list td, table.field-list th {
+ border: 0 !important;
+}
+
+.field-list ul {
+ margin: 0;
+ padding-left: 1em;
+}
+
+.field-list p {
+ margin: 0;
+}
/* -- other body styles ----------------------------------------------------- */
@@ -431,15 +433,6 @@ dl.glossary dt {
font-size: 1.1em;
}
-.field-list ul {
- margin: 0;
- padding-left: 1em;
-}
-
-.field-list p {
- margin: 0;
-}
-
.optional {
font-size: 1.3em;
}
@@ -589,6 +582,16 @@ span.eqno {
float: right;
}
+span.eqno a.headerlink {
+ position: relative;
+ left: 0px;
+ z-index: 1;
+}
+
+div.math:hover a.headerlink {
+ visibility: visible;
+}
+
/* -- printout stylesheet --------------------------------------------------- */
@media print {
diff --git a/sphinx/themes/basic/static/comment-bright.png b/sphinx/themes/basic/static/comment-bright.png
index 551517b8c..15e27edb1 100644
--- a/sphinx/themes/basic/static/comment-bright.png
+++ b/sphinx/themes/basic/static/comment-bright.png
Binary files differ
diff --git a/sphinx/themes/basic/static/comment-close.png b/sphinx/themes/basic/static/comment-close.png
index 09b54be46..4d91bcf57 100644
--- a/sphinx/themes/basic/static/comment-close.png
+++ b/sphinx/themes/basic/static/comment-close.png
Binary files differ
diff --git a/sphinx/themes/basic/static/comment.png b/sphinx/themes/basic/static/comment.png
index 92feb52b8..dfbc0cbd5 100644
--- a/sphinx/themes/basic/static/comment.png
+++ b/sphinx/themes/basic/static/comment.png
Binary files differ
diff --git a/sphinx/themes/basic/static/down-pressed.png b/sphinx/themes/basic/static/down-pressed.png
index 7c30d004b..5756c8cad 100644
--- a/sphinx/themes/basic/static/down-pressed.png
+++ b/sphinx/themes/basic/static/down-pressed.png
Binary files differ
diff --git a/sphinx/themes/basic/static/down.png b/sphinx/themes/basic/static/down.png
index f48098a43..1b3bdad2c 100644
--- a/sphinx/themes/basic/static/down.png
+++ b/sphinx/themes/basic/static/down.png
Binary files differ
diff --git a/sphinx/themes/basic/static/file.png b/sphinx/themes/basic/static/file.png
index 254c60bfb..a858a410e 100644
--- a/sphinx/themes/basic/static/file.png
+++ b/sphinx/themes/basic/static/file.png
Binary files differ
diff --git a/sphinx/themes/basic/static/jquery-1.11.1.js b/sphinx/themes/basic/static/jquery-3.1.0.js
index d4b67f7e6..f2fc27478 100644
--- a/sphinx/themes/basic/static/jquery-1.11.1.js
+++ b/sphinx/themes/basic/static/jquery-3.1.0.js
@@ -1,27 +1,30 @@
+/*eslint-disable no-unused-vars*/
/*!
- * jQuery JavaScript Library v1.11.1
- * http://jquery.com/
+ * jQuery JavaScript Library v3.1.0
+ * https://jquery.com/
*
* Includes Sizzle.js
- * http://sizzlejs.com/
+ * https://sizzlejs.com/
*
- * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
+ * Copyright jQuery Foundation and other contributors
* Released under the MIT license
- * http://jquery.org/license
+ * https://jquery.org/license
*
- * Date: 2014-05-01T17:42Z
+ * Date: 2016-07-07T21:44Z
*/
+( function( global, factory ) {
-(function( global, factory ) {
+ "use strict";
if ( typeof module === "object" && typeof module.exports === "object" ) {
- // For CommonJS and CommonJS-like environments where a proper window is present,
- // execute the factory and get jQuery
- // For environments that do not inherently posses a window with a document
- // (such as Node.js), expose a jQuery-making factory as module.exports
- // This accentuates the need for the creation of a real window
+
+ // For CommonJS and CommonJS-like environments where a proper `window`
+ // is present, execute the factory and get jQuery.
+ // For environments that do not have a `window` with a `document`
+ // (such as Node.js), expose a factory as module.exports.
+ // This accentuates the need for the creation of a real `window`.
// e.g. var jQuery = require("jquery")(window);
- // See ticket #14549 for more info
+ // See ticket #14549 for more info.
module.exports = global.document ?
factory( global, true ) :
function( w ) {
@@ -35,23 +38,27 @@
}
// Pass this if window is not defined yet
-}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
-// Can't do this because several apps including ASP.NET trace
-// the stack via arguments.caller.callee and Firefox dies if
-// you try to trace through "use strict" call chains. (#13335)
-// Support: Firefox 18+
-//
+// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
+// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
+// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
+// enough that all such attempts are guarded in a try block.
+"use strict";
-var deletedIds = [];
+var arr = [];
-var slice = deletedIds.slice;
+var document = window.document;
-var concat = deletedIds.concat;
+var getProto = Object.getPrototypeOf;
-var push = deletedIds.push;
+var slice = arr.slice;
-var indexOf = deletedIds.indexOf;
+var concat = arr.concat;
+
+var push = arr.push;
+
+var indexOf = arr.indexOf;
var class2type = {};
@@ -59,27 +66,46 @@ var toString = class2type.toString;
var hasOwn = class2type.hasOwnProperty;
+var fnToString = hasOwn.toString;
+
+var ObjectFunctionString = fnToString.call( Object );
+
var support = {};
+ function DOMEval( code, doc ) {
+ doc = doc || document;
+
+ var script = doc.createElement( "script" );
+
+ script.text = code;
+ doc.head.appendChild( script ).parentNode.removeChild( script );
+ }
+/* global Symbol */
+// Defining this global in .eslintrc would create a danger of using the global
+// unguarded in another place, it seems safer to define global only for this module
+
+
+
var
- version = "1.11.1",
+ version = "3.1.0",
// Define a local copy of jQuery
jQuery = function( selector, context ) {
+
// The jQuery object is actually just the init constructor 'enhanced'
// Need init if jQuery is called (just allow error to be thrown if not included)
return new jQuery.fn.init( selector, context );
},
- // Support: Android<4.1, IE<9
+ // Support: Android <=4.0 only
// Make sure we trim BOM and NBSP
rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
// Matches dashed string for camelizing
rmsPrefix = /^-ms-/,
- rdashAlpha = /-([\da-z])/gi,
+ rdashAlpha = /-([a-z])/g,
// Used by jQuery.camelCase as callback to replace()
fcamelCase = function( all, letter ) {
@@ -87,14 +113,12 @@ var
};
jQuery.fn = jQuery.prototype = {
+
// The current version of jQuery being used
jquery: version,
constructor: jQuery,
- // Start with an empty selector
- selector: "",
-
// The default length of a jQuery object is 0
length: 0,
@@ -123,23 +147,20 @@ jQuery.fn = jQuery.prototype = {
// Add the old object onto the stack (as a reference)
ret.prevObject = this;
- ret.context = this.context;
// Return the newly-formed element set
return ret;
},
// Execute a callback for every element in the matched set.
- // (You can seed the arguments with an array of args, but this is
- // only used internally.)
- each: function( callback, args ) {
- return jQuery.each( this, callback, args );
+ each: function( callback ) {
+ return jQuery.each( this, callback );
},
map: function( callback ) {
- return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return this.pushStack( jQuery.map( this, function( elem, i ) {
return callback.call( elem, i, elem );
- }));
+ } ) );
},
slice: function() {
@@ -157,23 +178,23 @@ jQuery.fn = jQuery.prototype = {
eq: function( i ) {
var len = this.length,
j = +i + ( i < 0 ? len : 0 );
- return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
+ return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
},
end: function() {
- return this.prevObject || this.constructor(null);
+ return this.prevObject || this.constructor();
},
// For internal use only.
// Behaves like an Array's method, not like a jQuery method.
push: push,
- sort: deletedIds.sort,
- splice: deletedIds.splice
+ sort: arr.sort,
+ splice: arr.splice
};
jQuery.extend = jQuery.fn.extend = function() {
- var src, copyIsArray, copy, name, options, clone,
- target = arguments[0] || {},
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[ 0 ] || {},
i = 1,
length = arguments.length,
deep = false;
@@ -182,25 +203,27 @@ jQuery.extend = jQuery.fn.extend = function() {
if ( typeof target === "boolean" ) {
deep = target;
- // skip the boolean and the target
+ // Skip the boolean and the target
target = arguments[ i ] || {};
i++;
}
// Handle case when target is a string or something (possible in deep copy)
- if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
target = {};
}
- // extend jQuery itself if only one argument is passed
+ // Extend jQuery itself if only one argument is passed
if ( i === length ) {
target = this;
i--;
}
for ( ; i < length; i++ ) {
+
// Only deal with non-null/undefined values
- if ( (options = arguments[ i ]) != null ) {
+ if ( ( options = arguments[ i ] ) != null ) {
+
// Extend the base object
for ( name in options ) {
src = target[ name ];
@@ -212,13 +235,15 @@ jQuery.extend = jQuery.fn.extend = function() {
}
// Recurse if we're merging plain objects or arrays
- if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
+ ( copyIsArray = jQuery.isArray( copy ) ) ) ) {
+
if ( copyIsArray ) {
copyIsArray = false;
- clone = src && jQuery.isArray(src) ? src : [];
+ clone = src && jQuery.isArray( src ) ? src : [];
} else {
- clone = src && jQuery.isPlainObject(src) ? src : {};
+ clone = src && jQuery.isPlainObject( src ) ? src : {};
}
// Never move original objects, clone them
@@ -236,7 +261,8 @@ jQuery.extend = jQuery.fn.extend = function() {
return target;
};
-jQuery.extend({
+jQuery.extend( {
+
// Unique for each copy of jQuery on the page
expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
@@ -249,98 +275,81 @@ jQuery.extend({
noop: function() {},
- // See test/unit/core.js for details concerning isFunction.
- // Since version 1.3, DOM methods and functions like alert
- // aren't supported. They return false on IE (#2968).
isFunction: function( obj ) {
- return jQuery.type(obj) === "function";
+ return jQuery.type( obj ) === "function";
},
- isArray: Array.isArray || function( obj ) {
- return jQuery.type(obj) === "array";
- },
+ isArray: Array.isArray,
isWindow: function( obj ) {
- /* jshint eqeqeq: false */
- return obj != null && obj == obj.window;
+ return obj != null && obj === obj.window;
},
isNumeric: function( obj ) {
- // parseFloat NaNs numeric-cast false positives (null|true|false|"")
- // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
- // subtraction forces infinities to NaN
- return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0;
- },
- isEmptyObject: function( obj ) {
- var name;
- for ( name in obj ) {
- return false;
- }
- return true;
+ // As of jQuery 3.0, isNumeric is limited to
+ // strings and numbers (primitives or objects)
+ // that can be coerced to finite numbers (gh-2662)
+ var type = jQuery.type( obj );
+ return ( type === "number" || type === "string" ) &&
+
+ // parseFloat NaNs numeric-cast false positives ("")
+ // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+ // subtraction forces infinities to NaN
+ !isNaN( obj - parseFloat( obj ) );
},
isPlainObject: function( obj ) {
- var key;
+ var proto, Ctor;
- // Must be an Object.
- // Because of IE, we also have to check the presence of the constructor property.
- // Make sure that DOM nodes and window objects don't pass through, as well
- if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ // Detect obvious negatives
+ // Use toString instead of jQuery.type to catch host objects
+ if ( !obj || toString.call( obj ) !== "[object Object]" ) {
return false;
}
- try {
- // Not own constructor property must be Object
- if ( obj.constructor &&
- !hasOwn.call(obj, "constructor") &&
- !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
- return false;
- }
- } catch ( e ) {
- // IE8,9 Will throw exceptions on certain host objects #9897
- return false;
- }
+ proto = getProto( obj );
- // Support: IE<9
- // Handle iteration over inherited properties before own properties.
- if ( support.ownLast ) {
- for ( key in obj ) {
- return hasOwn.call( obj, key );
- }
+ // Objects with no prototype (e.g., `Object.create( null )`) are plain
+ if ( !proto ) {
+ return true;
}
- // Own properties are enumerated firstly, so to speed up,
- // if last one is own, then all properties are own.
- for ( key in obj ) {}
+ // Objects with prototype are plain iff they were constructed by a global Object function
+ Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
+ return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
+ },
- return key === undefined || hasOwn.call( obj, key );
+ isEmptyObject: function( obj ) {
+
+ /* eslint-disable no-unused-vars */
+ // See https://github.com/eslint/eslint/issues/6125
+ var name;
+
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
},
type: function( obj ) {
if ( obj == null ) {
return obj + "";
}
+
+ // Support: Android <=2.3 only (functionish RegExp)
return typeof obj === "object" || typeof obj === "function" ?
- class2type[ toString.call(obj) ] || "object" :
+ class2type[ toString.call( obj ) ] || "object" :
typeof obj;
},
// Evaluates a script in a global context
- // Workarounds based on findings by Jim Driscoll
- // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
- globalEval: function( data ) {
- if ( data && jQuery.trim( data ) ) {
- // We use execScript on Internet Explorer
- // We use an anonymous function so that context is window
- // rather than jQuery in Firefox
- ( window.execScript || function( data ) {
- window[ "eval" ].call( window, data );
- } )( data );
- }
+ globalEval: function( code ) {
+ DOMEval( code );
},
// Convert dashed to camelCase; used by the css and data modules
+ // Support: IE <=9 - 11, Edge 12 - 13
// Microsoft forgot to hump their vendor prefix (#9572)
camelCase: function( string ) {
return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
@@ -350,49 +359,20 @@ jQuery.extend({
return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
},
- // args is for internal usage only
- each: function( obj, callback, args ) {
- var value,
- i = 0,
- length = obj.length,
- isArray = isArraylike( obj );
-
- if ( args ) {
- if ( isArray ) {
- for ( ; i < length; i++ ) {
- value = callback.apply( obj[ i ], args );
-
- if ( value === false ) {
- break;
- }
- }
- } else {
- for ( i in obj ) {
- value = callback.apply( obj[ i ], args );
+ each: function( obj, callback ) {
+ var length, i = 0;
- if ( value === false ) {
- break;
- }
+ if ( isArrayLike( obj ) ) {
+ length = obj.length;
+ for ( ; i < length; i++ ) {
+ if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+ break;
}
}
-
- // A special, fast, case for the most common use of each
} else {
- if ( isArray ) {
- for ( ; i < length; i++ ) {
- value = callback.call( obj[ i ], i, obj[ i ] );
-
- if ( value === false ) {
- break;
- }
- }
- } else {
- for ( i in obj ) {
- value = callback.call( obj[ i ], i, obj[ i ] );
-
- if ( value === false ) {
- break;
- }
+ for ( i in obj ) {
+ if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+ break;
}
}
}
@@ -400,7 +380,7 @@ jQuery.extend({
return obj;
},
- // Support: Android<4.1, IE<9
+ // Support: Android <=4.0 only
trim: function( text ) {
return text == null ?
"" :
@@ -412,7 +392,7 @@ jQuery.extend({
var ret = results || [];
if ( arr != null ) {
- if ( isArraylike( Object(arr) ) ) {
+ if ( isArrayLike( Object( arr ) ) ) {
jQuery.merge( ret,
typeof arr === "string" ?
[ arr ] : arr
@@ -426,42 +406,18 @@ jQuery.extend({
},
inArray: function( elem, arr, i ) {
- var len;
-
- if ( arr ) {
- if ( indexOf ) {
- return indexOf.call( arr, elem, i );
- }
-
- len = arr.length;
- i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
-
- for ( ; i < len; i++ ) {
- // Skip accessing in sparse arrays
- if ( i in arr && arr[ i ] === elem ) {
- return i;
- }
- }
- }
-
- return -1;
+ return arr == null ? -1 : indexOf.call( arr, elem, i );
},
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
merge: function( first, second ) {
var len = +second.length,
j = 0,
i = first.length;
- while ( j < len ) {
- first[ i++ ] = second[ j++ ];
- }
-
- // Support: IE<9
- // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
- if ( len !== len ) {
- while ( second[j] !== undefined ) {
- first[ i++ ] = second[ j++ ];
- }
+ for ( ; j < len; j++ ) {
+ first[ i++ ] = second[ j ];
}
first.length = i;
@@ -490,14 +446,13 @@ jQuery.extend({
// arg is for internal usage only
map: function( elems, callback, arg ) {
- var value,
+ var length, value,
i = 0,
- length = elems.length,
- isArray = isArraylike( elems ),
ret = [];
// Go through the array, translating each of the items to their new values
- if ( isArray ) {
+ if ( isArrayLike( elems ) ) {
+ length = elems.length;
for ( ; i < length; i++ ) {
value = callback( elems[ i ], i, arg );
@@ -527,7 +482,7 @@ jQuery.extend({
// Bind a function to a context, optionally partially applying any
// arguments.
proxy: function( fn, context ) {
- var args, proxy, tmp;
+ var tmp, args, proxy;
if ( typeof context === "string" ) {
tmp = fn[ context ];
@@ -553,45 +508,49 @@ jQuery.extend({
return proxy;
},
- now: function() {
- return +( new Date() );
- },
+ now: Date.now,
// jQuery.support is not used in Core but other projects attach their
// properties to it so it needs to exist.
support: support
-});
+} );
+
+if ( typeof Symbol === "function" ) {
+ jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
+}
// Populate the class2type map
-jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
+function( i, name ) {
class2type[ "[object " + name + "]" ] = name.toLowerCase();
-});
+} );
+
+function isArrayLike( obj ) {
-function isArraylike( obj ) {
- var length = obj.length,
+ // Support: real iOS 8.2 only (not reproducible in simulator)
+ // `in` check used to prevent JIT error (gh-2145)
+ // hasOwn isn't used here due to false negatives
+ // regarding Nodelist length in IE
+ var length = !!obj && "length" in obj && obj.length,
type = jQuery.type( obj );
if ( type === "function" || jQuery.isWindow( obj ) ) {
return false;
}
- if ( obj.nodeType === 1 && length ) {
- return true;
- }
-
return type === "array" || length === 0 ||
typeof length === "number" && length > 0 && ( length - 1 ) in obj;
}
var Sizzle =
/*!
- * Sizzle CSS Selector Engine v1.10.19
- * http://sizzlejs.com/
+ * Sizzle CSS Selector Engine v2.3.0
+ * https://sizzlejs.com/
*
- * Copyright 2013 jQuery Foundation, Inc. and other contributors
+ * Copyright jQuery Foundation and other contributors
* Released under the MIT license
* http://jquery.org/license
*
- * Date: 2014-04-18
+ * Date: 2016-01-04
*/
(function( window ) {
@@ -618,7 +577,7 @@ var i,
contains,
// Instance-specific data
- expando = "sizzle" + -(new Date()),
+ expando = "sizzle" + 1 * new Date(),
preferredDoc = window.document,
dirruns = 0,
done = 0,
@@ -632,10 +591,6 @@ var i,
return 0;
},
- // General-purpose constants
- strundefined = typeof undefined,
- MAX_NEGATIVE = 1 << 31,
-
// Instance methods
hasOwn = ({}).hasOwnProperty,
arr = [],
@@ -643,12 +598,13 @@ var i,
push_native = arr.push,
push = arr.push,
slice = arr.slice,
- // Use a stripped-down indexOf if we can't use a native one
- indexOf = arr.indexOf || function( elem ) {
+ // Use a stripped-down indexOf as it's faster than native
+ // https://jsperf.com/thor-indexof-vs-for/5
+ indexOf = function( list, elem ) {
var i = 0,
- len = this.length;
+ len = list.length;
for ( ; i < len; i++ ) {
- if ( this[i] === elem ) {
+ if ( list[i] === elem ) {
return i;
}
}
@@ -659,25 +615,21 @@ var i,
// Regular expressions
- // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+ // http://www.w3.org/TR/css3-selectors/#whitespace
whitespace = "[\\x20\\t\\r\\n\\f]",
- // http://www.w3.org/TR/css3-syntax/#characters
- characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
- // Loosely modeled on CSS identifier characters
- // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
- // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
- identifier = characterEncoding.replace( "w", "w#" ),
+ // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
- attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
+ attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
// Operator (capture 2)
"*([*^$|!~]?=)" + whitespace +
// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
"*\\]",
- pseudos = ":(" + characterEncoding + ")(?:\\((" +
+ pseudos = ":(" + identifier + ")(?:\\((" +
// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
// 1. quoted (capture 3; capture 4 or capture 5)
"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
@@ -688,6 +640,7 @@ var i,
")\\)|)",
// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rwhitespace = new RegExp( whitespace + "+", "g" ),
rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
@@ -699,9 +652,9 @@ var i,
ridentifier = new RegExp( "^" + identifier + "$" ),
matchExpr = {
- "ID": new RegExp( "^#(" + characterEncoding + ")" ),
- "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
- "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+ "ID": new RegExp( "^#(" + identifier + ")" ),
+ "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
+ "TAG": new RegExp( "^(" + identifier + "|[*])" ),
"ATTR": new RegExp( "^" + attributes ),
"PSEUDO": new RegExp( "^" + pseudos ),
"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
@@ -723,9 +676,9 @@ var i,
rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
rsibling = /[+~]/,
- rescape = /'|\\/g,
- // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+ // CSS escapes
+ // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
funescape = function( _, escaped, escapedWhitespace ) {
var high = "0x" + escaped - 0x10000;
@@ -739,7 +692,41 @@ var i,
String.fromCharCode( high + 0x10000 ) :
// Supplemental Plane codepoint (surrogate pair)
String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
- };
+ },
+
+ // CSS string/identifier serialization
+ // https://drafts.csswg.org/cssom/#common-serializing-idioms
+ rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,
+ fcssescape = function( ch, asCodePoint ) {
+ if ( asCodePoint ) {
+
+ // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
+ if ( ch === "\0" ) {
+ return "\uFFFD";
+ }
+
+ // Control characters and (dependent upon position) numbers get escaped as code points
+ return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
+ }
+
+ // Other potentially-special ASCII characters get backslash-escaped
+ return "\\" + ch;
+ },
+
+ // Used for iframes
+ // See setDocument()
+ // Removing the function wrapper causes a "Permission Denied"
+ // error in IE
+ unloadHandler = function() {
+ setDocument();
+ },
+
+ disabledAncestor = addCombinator(
+ function( elem ) {
+ return elem.disabled === true;
+ },
+ { dir: "parentNode", next: "legend" }
+ );
// Optimize for push.apply( _, NodeList )
try {
@@ -771,104 +758,128 @@ try {
}
function Sizzle( selector, context, results, seed ) {
- var match, elem, m, nodeType,
- // QSA vars
- i, groups, old, nid, newContext, newSelector;
+ var m, i, elem, nid, match, groups, newSelector,
+ newContext = context && context.ownerDocument,
- if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
- setDocument( context );
- }
+ // nodeType defaults to 9, since context defaults to document
+ nodeType = context ? context.nodeType : 9;
- context = context || document;
results = results || [];
- if ( !selector || typeof selector !== "string" ) {
+ // Return early from calls with invalid selector or context
+ if ( typeof selector !== "string" || !selector ||
+ nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
+
return results;
}
- if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
- return [];
- }
+ // Try to shortcut find operations (as opposed to filters) in HTML documents
+ if ( !seed ) {
- if ( documentIsHTML && !seed ) {
-
- // Shortcuts
- if ( (match = rquickExpr.exec( selector )) ) {
- // Speed-up: Sizzle("#ID")
- if ( (m = match[1]) ) {
- if ( nodeType === 9 ) {
- elem = context.getElementById( m );
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document (jQuery #6963)
- if ( elem && elem.parentNode ) {
- // Handle the case where IE, Opera, and Webkit return items
- // by name instead of ID
- if ( elem.id === m ) {
- results.push( elem );
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+ setDocument( context );
+ }
+ context = context || document;
+
+ if ( documentIsHTML ) {
+
+ // If the selector is sufficiently simple, try using a "get*By*" DOM method
+ // (excepting DocumentFragment context, where the methods don't exist)
+ if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
+
+ // ID selector
+ if ( (m = match[1]) ) {
+
+ // Document context
+ if ( nodeType === 9 ) {
+ if ( (elem = context.getElementById( m )) ) {
+
+ // Support: IE, Opera, Webkit
+ // TODO: identify versions
+ // getElementById can match elements by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
return results;
}
+
+ // Element context
} else {
- return results;
- }
- } else {
- // Context is not a document
- if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
- contains( context, elem ) && elem.id === m ) {
- results.push( elem );
- return results;
+
+ // Support: IE, Opera, Webkit
+ // TODO: identify versions
+ // getElementById can match elements by name instead of ID
+ if ( newContext && (elem = newContext.getElementById( m )) &&
+ contains( context, elem ) &&
+ elem.id === m ) {
+
+ results.push( elem );
+ return results;
+ }
}
- }
- // Speed-up: Sizzle("TAG")
- } else if ( match[2] ) {
- push.apply( results, context.getElementsByTagName( selector ) );
- return results;
+ // Type selector
+ } else if ( match[2] ) {
+ push.apply( results, context.getElementsByTagName( selector ) );
+ return results;
- // Speed-up: Sizzle(".CLASS")
- } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
- push.apply( results, context.getElementsByClassName( m ) );
- return results;
+ // Class selector
+ } else if ( (m = match[3]) && support.getElementsByClassName &&
+ context.getElementsByClassName ) {
+
+ push.apply( results, context.getElementsByClassName( m ) );
+ return results;
+ }
}
- }
- // QSA path
- if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
- nid = old = expando;
- newContext = context;
- newSelector = nodeType === 9 && selector;
+ // Take advantage of querySelectorAll
+ if ( support.qsa &&
+ !compilerCache[ selector + " " ] &&
+ (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
- // qSA works strangely on Element-rooted queries
- // We can work around this by specifying an extra ID on the root
- // and working up from there (Thanks to Andrew Dupont for the technique)
- // IE 8 doesn't work on object elements
- if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
- groups = tokenize( selector );
+ if ( nodeType !== 1 ) {
+ newContext = context;
+ newSelector = selector;
- if ( (old = context.getAttribute("id")) ) {
- nid = old.replace( rescape, "\\$&" );
- } else {
- context.setAttribute( "id", nid );
- }
- nid = "[id='" + nid + "'] ";
+ // qSA looks outside Element context, which is not what we want
+ // Thanks to Andrew Dupont for this workaround technique
+ // Support: IE <=8
+ // Exclude object elements
+ } else if ( context.nodeName.toLowerCase() !== "object" ) {
- i = groups.length;
- while ( i-- ) {
- groups[i] = nid + toSelector( groups[i] );
+ // Capture the context ID, setting it first if necessary
+ if ( (nid = context.getAttribute( "id" )) ) {
+ nid = nid.replace( rcssescape, fcssescape );
+ } else {
+ context.setAttribute( "id", (nid = expando) );
+ }
+
+ // Prefix every selector in the list
+ groups = tokenize( selector );
+ i = groups.length;
+ while ( i-- ) {
+ groups[i] = "#" + nid + " " + toSelector( groups[i] );
+ }
+ newSelector = groups.join( "," );
+
+ // Expand context for sibling selectors
+ newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
+ context;
}
- newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
- newSelector = groups.join(",");
- }
- if ( newSelector ) {
- try {
- push.apply( results,
- newContext.querySelectorAll( newSelector )
- );
- return results;
- } catch(qsaError) {
- } finally {
- if ( !old ) {
- context.removeAttribute("id");
+ if ( newSelector ) {
+ try {
+ push.apply( results,
+ newContext.querySelectorAll( newSelector )
+ );
+ return results;
+ } catch ( qsaError ) {
+ } finally {
+ if ( nid === expando ) {
+ context.removeAttribute( "id" );
+ }
}
}
}
@@ -881,7 +892,7 @@ function Sizzle( selector, context, results, seed ) {
/**
* Create key-value caches of limited size
- * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ * @returns {function(string, object)} Returns the Object data after storing it on itself with
* property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
* deleting the oldest entry
*/
@@ -910,22 +921,22 @@ function markFunction( fn ) {
/**
* Support testing using an element
- * @param {Function} fn Passed the created div and expects a boolean result
+ * @param {Function} fn Passed the created element and returns a boolean result
*/
function assert( fn ) {
- var div = document.createElement("div");
+ var el = document.createElement("fieldset");
try {
- return !!fn( div );
+ return !!fn( el );
} catch (e) {
return false;
} finally {
// Remove from its parent by default
- if ( div.parentNode ) {
- div.parentNode.removeChild( div );
+ if ( el.parentNode ) {
+ el.parentNode.removeChild( el );
}
// release memory in IE
- div = null;
+ el = null;
}
}
@@ -936,7 +947,7 @@ function assert( fn ) {
*/
function addHandle( attrs, handler ) {
var arr = attrs.split("|"),
- i = attrs.length;
+ i = arr.length;
while ( i-- ) {
Expr.attrHandle[ arr[i] ] = handler;
@@ -952,8 +963,7 @@ function addHandle( attrs, handler ) {
function siblingCheck( a, b ) {
var cur = b && a,
diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
- ( ~b.sourceIndex || MAX_NEGATIVE ) -
- ( ~a.sourceIndex || MAX_NEGATIVE );
+ a.sourceIndex - b.sourceIndex;
// Use IE sourceIndex if available on both nodes
if ( diff ) {
@@ -995,6 +1005,34 @@ function createButtonPseudo( type ) {
}
/**
+ * Returns a function to use in pseudos for :enabled/:disabled
+ * @param {Boolean} disabled true for :disabled; false for :enabled
+ */
+function createDisabledPseudo( disabled ) {
+ // Known :disabled false positives:
+ // IE: *[disabled]:not(button, input, select, textarea, optgroup, option, menuitem, fieldset)
+ // not IE: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
+ return function( elem ) {
+
+ // Check form elements and option elements for explicit disabling
+ return "label" in elem && elem.disabled === disabled ||
+ "form" in elem && elem.disabled === disabled ||
+
+ // Check non-disabled form elements for fieldset[disabled] ancestors
+ "form" in elem && elem.disabled === false && (
+ // Support: IE6-11+
+ // Ancestry is covered for us
+ elem.isDisabled === disabled ||
+
+ // Otherwise, assume any non-<option> under fieldset[disabled] is disabled
+ /* jshint -W018 */
+ elem.isDisabled !== !disabled &&
+ ("label" in elem || !disabledAncestor( elem )) !== disabled
+ );
+ };
+}
+
+/**
* Returns a function to use in pseudos for positionals
* @param {Function} fn
*/
@@ -1022,7 +1060,7 @@ function createPositionalPseudo( fn ) {
* @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
*/
function testContext( context ) {
- return context && typeof context.getElementsByTagName !== strundefined && context;
+ return context && typeof context.getElementsByTagName !== "undefined" && context;
}
// Expose support vars for convenience
@@ -1046,36 +1084,31 @@ isXML = Sizzle.isXML = function( elem ) {
* @returns {Object} Returns the current document
*/
setDocument = Sizzle.setDocument = function( node ) {
- var hasCompare,
- doc = node ? node.ownerDocument || node : preferredDoc,
- parent = doc.defaultView;
+ var hasCompare, subWindow,
+ doc = node ? node.ownerDocument || node : preferredDoc;
- // If no document and documentElement is available, return
+ // Return early if doc is invalid or already selected
if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
return document;
}
- // Set our document
+ // Update global variables
document = doc;
- docElem = doc.documentElement;
-
- // Support tests
- documentIsHTML = !isXML( doc );
-
- // Support: IE>8
- // If iframe document is assigned to "document" variable and if iframe has been reloaded,
- // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
- // IE6-8 do not support the defaultView property so parent will be undefined
- if ( parent && parent !== parent.top ) {
- // IE11 does not have attachEvent, so all must suffer
- if ( parent.addEventListener ) {
- parent.addEventListener( "unload", function() {
- setDocument();
- }, false );
- } else if ( parent.attachEvent ) {
- parent.attachEvent( "onunload", function() {
- setDocument();
- });
+ docElem = document.documentElement;
+ documentIsHTML = !isXML( document );
+
+ // Support: IE 9-11, Edge
+ // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
+ if ( preferredDoc !== document &&
+ (subWindow = document.defaultView) && subWindow.top !== subWindow ) {
+
+ // Support: IE 11, Edge
+ if ( subWindow.addEventListener ) {
+ subWindow.addEventListener( "unload", unloadHandler, false );
+
+ // Support: IE 9 - 10 only
+ } else if ( subWindow.attachEvent ) {
+ subWindow.attachEvent( "onunload", unloadHandler );
}
}
@@ -1083,50 +1116,40 @@ setDocument = Sizzle.setDocument = function( node ) {
---------------------------------------------------------------------- */
// Support: IE<8
- // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
- support.attributes = assert(function( div ) {
- div.className = "i";
- return !div.getAttribute("className");
+ // Verify that getAttribute really returns attributes and not properties
+ // (excepting IE8 booleans)
+ support.attributes = assert(function( el ) {
+ el.className = "i";
+ return !el.getAttribute("className");
});
/* getElement(s)By*
---------------------------------------------------------------------- */
// Check if getElementsByTagName("*") returns only elements
- support.getElementsByTagName = assert(function( div ) {
- div.appendChild( doc.createComment("") );
- return !div.getElementsByTagName("*").length;
+ support.getElementsByTagName = assert(function( el ) {
+ el.appendChild( document.createComment("") );
+ return !el.getElementsByTagName("*").length;
});
- // Check if getElementsByClassName can be trusted
- support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
- div.innerHTML = "<div class='a'></div><div class='a i'></div>";
-
- // Support: Safari<4
- // Catch class over-caching
- div.firstChild.className = "i";
- // Support: Opera<10
- // Catch gEBCN failure to find non-leading classes
- return div.getElementsByClassName("i").length === 2;
- });
+ // Support: IE<9
+ support.getElementsByClassName = rnative.test( document.getElementsByClassName );
// Support: IE<10
// Check if getElementById returns elements by name
- // The broken getElementById methods don't pick up programatically-set names,
+ // The broken getElementById methods don't pick up programmatically-set names,
// so use a roundabout getElementsByName test
- support.getById = assert(function( div ) {
- docElem.appendChild( div ).id = expando;
- return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
+ support.getById = assert(function( el ) {
+ docElem.appendChild( el ).id = expando;
+ return !document.getElementsByName || !document.getElementsByName( expando ).length;
});
// ID find and filter
if ( support.getById ) {
Expr.find["ID"] = function( id, context ) {
- if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
+ if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
var m = context.getElementById( id );
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document #6963
- return m && m.parentNode ? [ m ] : [];
+ return m ? [ m ] : [];
}
};
Expr.filter["ID"] = function( id ) {
@@ -1143,7 +1166,8 @@ setDocument = Sizzle.setDocument = function( node ) {
Expr.filter["ID"] = function( id ) {
var attrId = id.replace( runescape, funescape );
return function( elem ) {
- var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
+ var node = typeof elem.getAttributeNode !== "undefined" &&
+ elem.getAttributeNode("id");
return node && node.value === attrId;
};
};
@@ -1152,14 +1176,20 @@ setDocument = Sizzle.setDocument = function( node ) {
// Tag
Expr.find["TAG"] = support.getElementsByTagName ?
function( tag, context ) {
- if ( typeof context.getElementsByTagName !== strundefined ) {
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
return context.getElementsByTagName( tag );
+
+ // DocumentFragment nodes don't have gEBTN
+ } else if ( support.qsa ) {
+ return context.querySelectorAll( tag );
}
} :
+
function( tag, context ) {
var elem,
tmp = [],
i = 0,
+ // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
results = context.getElementsByTagName( tag );
// Filter out possible comments
@@ -1177,7 +1207,7 @@ setDocument = Sizzle.setDocument = function( node ) {
// Class
Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
- if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
+ if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
return context.getElementsByClassName( className );
}
};
@@ -1194,63 +1224,87 @@ setDocument = Sizzle.setDocument = function( node ) {
// We allow this because of a bug in IE8/9 that throws an error
// whenever `document.activeElement` is accessed on an iframe
// So, we allow :focus to pass through QSA all the time to avoid the IE error
- // See http://bugs.jquery.com/ticket/13378
+ // See https://bugs.jquery.com/ticket/13378
rbuggyQSA = [];
- if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
+ if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
// Build QSA regex
// Regex strategy adopted from Diego Perini
- assert(function( div ) {
+ assert(function( el ) {
// Select is set to empty string on purpose
// This is to test IE's treatment of not explicitly
// setting a boolean content attribute,
// since its presence should be enough
- // http://bugs.jquery.com/ticket/12359
- div.innerHTML = "<select msallowclip=''><option selected=''></option></select>";
+ // https://bugs.jquery.com/ticket/12359
+ docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
+ "<select id='" + expando + "-\r\\' msallowcapture=''>" +
+ "<option selected=''></option></select>";
// Support: IE8, Opera 11-12.16
// Nothing should be selected when empty strings follow ^= or $= or *=
// The test attribute must be unknown in Opera but "safe" for WinRT
- // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
- if ( div.querySelectorAll("[msallowclip^='']").length ) {
+ // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+ if ( el.querySelectorAll("[msallowcapture^='']").length ) {
rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
}
// Support: IE8
// Boolean attributes and "value" are not treated correctly
- if ( !div.querySelectorAll("[selected]").length ) {
+ if ( !el.querySelectorAll("[selected]").length ) {
rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
}
+ // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
+ if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
+ rbuggyQSA.push("~=");
+ }
+
// Webkit/Opera - :checked should return selected option elements
// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
// IE8 throws error here and will not see later tests
- if ( !div.querySelectorAll(":checked").length ) {
+ if ( !el.querySelectorAll(":checked").length ) {
rbuggyQSA.push(":checked");
}
+
+ // Support: Safari 8+, iOS 8+
+ // https://bugs.webkit.org/show_bug.cgi?id=136851
+ // In-page `selector#id sibling-combinator selector` fails
+ if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
+ rbuggyQSA.push(".#.+[+~]");
+ }
});
- assert(function( div ) {
+ assert(function( el ) {
+ el.innerHTML = "<a href='' disabled='disabled'></a>" +
+ "<select disabled='disabled'><option/></select>";
+
// Support: Windows 8 Native Apps
// The type and name attributes are restricted during .innerHTML assignment
- var input = doc.createElement("input");
+ var input = document.createElement("input");
input.setAttribute( "type", "hidden" );
- div.appendChild( input ).setAttribute( "name", "D" );
+ el.appendChild( input ).setAttribute( "name", "D" );
// Support: IE8
// Enforce case-sensitivity of name attribute
- if ( div.querySelectorAll("[name=d]").length ) {
+ if ( el.querySelectorAll("[name=d]").length ) {
rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
}
// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
// IE8 throws error here and will not see later tests
- if ( !div.querySelectorAll(":enabled").length ) {
+ if ( el.querySelectorAll(":enabled").length !== 2 ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Support: IE9-11+
+ // IE's :disabled selector does not pick up the children of disabled fieldsets
+ docElem.appendChild( el ).disabled = true;
+ if ( el.querySelectorAll(":disabled").length !== 2 ) {
rbuggyQSA.push( ":enabled", ":disabled" );
}
// Opera 10-11 does not throw on post-comma invalid pseudos
- div.querySelectorAll("*,:x");
+ el.querySelectorAll("*,:x");
rbuggyQSA.push(",.*:");
});
}
@@ -1261,14 +1315,14 @@ setDocument = Sizzle.setDocument = function( node ) {
docElem.oMatchesSelector ||
docElem.msMatchesSelector) )) ) {
- assert(function( div ) {
+ assert(function( el ) {
// Check to see if it's possible to do matchesSelector
// on a disconnected node (IE 9)
- support.disconnectedMatch = matches.call( div, "div" );
+ support.disconnectedMatch = matches.call( el, "*" );
// This should fail with an exception
// Gecko does not error, returns false instead
- matches.call( div, "[s!='']:x" );
+ matches.call( el, "[s!='']:x" );
rbuggyMatches.push( "!=", pseudos );
});
}
@@ -1281,7 +1335,7 @@ setDocument = Sizzle.setDocument = function( node ) {
hasCompare = rnative.test( docElem.compareDocumentPosition );
// Element contains another
- // Purposefully does not implement inclusive descendent
+ // Purposefully self-exclusive
// As in, an element does not contain itself
contains = hasCompare || rnative.test( docElem.contains ) ?
function( a, b ) {
@@ -1335,16 +1389,16 @@ setDocument = Sizzle.setDocument = function( node ) {
(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
// Choose the first element that is related to our preferred document
- if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+ if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
return -1;
}
- if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+ if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
return 1;
}
// Maintain original order
return sortInput ?
- ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
0;
}
@@ -1366,12 +1420,12 @@ setDocument = Sizzle.setDocument = function( node ) {
// Parentless nodes are either documents or disconnected
if ( !aup || !bup ) {
- return a === doc ? -1 :
- b === doc ? 1 :
+ return a === document ? -1 :
+ b === document ? 1 :
aup ? -1 :
bup ? 1 :
sortInput ?
- ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
0;
// If the nodes are siblings, we can do a quick check
@@ -1404,7 +1458,7 @@ setDocument = Sizzle.setDocument = function( node ) {
0;
};
- return doc;
+ return document;
};
Sizzle.matches = function( expr, elements ) {
@@ -1421,6 +1475,7 @@ Sizzle.matchesSelector = function( elem, expr ) {
expr = expr.replace( rattributeQuotes, "='$1']" );
if ( support.matchesSelector && documentIsHTML &&
+ !compilerCache[ expr + " " ] &&
( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
@@ -1434,7 +1489,7 @@ Sizzle.matchesSelector = function( elem, expr ) {
elem.document && elem.document.nodeType !== 11 ) {
return ret;
}
- } catch(e) {}
+ } catch (e) {}
}
return Sizzle( expr, document, null, [ elem ] ).length > 0;
@@ -1469,6 +1524,10 @@ Sizzle.attr = function( elem, name ) {
null;
};
+Sizzle.escape = function( sel ) {
+ return (sel + "").replace( rcssescape, fcssescape );
+};
+
Sizzle.error = function( msg ) {
throw new Error( "Syntax error, unrecognized expression: " + msg );
};
@@ -1653,7 +1712,7 @@ Expr = Sizzle.selectors = {
return pattern ||
(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
classCache( className, function( elem ) {
- return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
+ return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
});
},
@@ -1675,7 +1734,7 @@ Expr = Sizzle.selectors = {
operator === "^=" ? check && result.indexOf( check ) === 0 :
operator === "*=" ? check && result.indexOf( check ) > -1 :
operator === "$=" ? check && result.slice( -check.length ) === check :
- operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
+ operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
false;
};
@@ -1694,11 +1753,12 @@ Expr = Sizzle.selectors = {
} :
function( elem, context, xml ) {
- var cache, outerCache, node, diff, nodeIndex, start,
+ var cache, uniqueCache, outerCache, node, nodeIndex, start,
dir = simple !== forward ? "nextSibling" : "previousSibling",
parent = elem.parentNode,
name = ofType && elem.nodeName.toLowerCase(),
- useCache = !xml && !ofType;
+ useCache = !xml && !ofType,
+ diff = false;
if ( parent ) {
@@ -1707,7 +1767,10 @@ Expr = Sizzle.selectors = {
while ( dir ) {
node = elem;
while ( (node = node[ dir ]) ) {
- if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+ if ( ofType ?
+ node.nodeName.toLowerCase() === name :
+ node.nodeType === 1 ) {
+
return false;
}
}
@@ -1721,11 +1784,21 @@ Expr = Sizzle.selectors = {
// non-xml :nth-child(...) stores cache data on `parent`
if ( forward && useCache ) {
+
// Seek `elem` from a previously-cached index
- outerCache = parent[ expando ] || (parent[ expando ] = {});
- cache = outerCache[ type ] || [];
- nodeIndex = cache[0] === dirruns && cache[1];
- diff = cache[0] === dirruns && cache[2];
+
+ // ...in a gzip-friendly way
+ node = parent;
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ cache = uniqueCache[ type ] || [];
+ nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+ diff = nodeIndex && cache[ 2 ];
node = nodeIndex && parent.childNodes[ nodeIndex ];
while ( (node = ++nodeIndex && node && node[ dir ] ||
@@ -1735,29 +1808,55 @@ Expr = Sizzle.selectors = {
// When found, cache indexes on `parent` and break
if ( node.nodeType === 1 && ++diff && node === elem ) {
- outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+ uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
break;
}
}
- // Use previously-cached element index if available
- } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
- diff = cache[1];
-
- // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
} else {
- // Use the same loop as above to seek `elem` from the start
- while ( (node = ++nodeIndex && node && node[ dir ] ||
- (diff = nodeIndex = 0) || start.pop()) ) {
+ // Use previously-cached element index if available
+ if ( useCache ) {
+ // ...in a gzip-friendly way
+ node = elem;
+ outerCache = node[ expando ] || (node[ expando ] = {});
- if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
- // Cache the index of each encountered element
- if ( useCache ) {
- (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
- }
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
- if ( node === elem ) {
- break;
+ cache = uniqueCache[ type ] || [];
+ nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+ diff = nodeIndex;
+ }
+
+ // xml :nth-child(...)
+ // or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ if ( diff === false ) {
+ // Use the same loop as above to seek `elem` from the start
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ if ( ( ofType ?
+ node.nodeName.toLowerCase() === name :
+ node.nodeType === 1 ) &&
+ ++diff ) {
+
+ // Cache the index of each encountered element
+ if ( useCache ) {
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ uniqueCache[ type ] = [ dirruns, diff ];
+ }
+
+ if ( node === elem ) {
+ break;
+ }
}
}
}
@@ -1795,7 +1894,7 @@ Expr = Sizzle.selectors = {
matched = fn( seed, argument ),
i = matched.length;
while ( i-- ) {
- idx = indexOf.call( seed, matched[i] );
+ idx = indexOf( seed, matched[i] );
seed[ idx ] = !( matches[ idx ] = matched[i] );
}
}) :
@@ -1834,6 +1933,8 @@ Expr = Sizzle.selectors = {
function( elem, context, xml ) {
input[0] = elem;
matcher( input, null, xml, results );
+ // Don't keep the element (issue #299)
+ input[0] = null;
return !results.pop();
};
}),
@@ -1845,6 +1946,7 @@ Expr = Sizzle.selectors = {
}),
"contains": markFunction(function( text ) {
+ text = text.replace( runescape, funescape );
return function( elem ) {
return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
};
@@ -1893,13 +1995,8 @@ Expr = Sizzle.selectors = {
},
// Boolean properties
- "enabled": function( elem ) {
- return elem.disabled === false;
- },
-
- "disabled": function( elem ) {
- return elem.disabled === true;
- },
+ "enabled": createDisabledPseudo( false ),
+ "disabled": createDisabledPseudo( true ),
"checked": function( elem ) {
// In CSS3, :checked should return both checked and selected elements
@@ -2101,7 +2198,9 @@ function toSelector( tokens ) {
function addCombinator( matcher, combinator, base ) {
var dir = combinator.dir,
- checkNonElements = base && dir === "parentNode",
+ skip = combinator.next,
+ key = skip || dir,
+ checkNonElements = base && key === "parentNode",
doneName = done++;
return combinator.first ?
@@ -2116,10 +2215,10 @@ function addCombinator( matcher, combinator, base ) {
// Check against all ancestor/preceding elements
function( elem, context, xml ) {
- var oldCache, outerCache,
+ var oldCache, uniqueCache, outerCache,
newCache = [ dirruns, doneName ];
- // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+ // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
if ( xml ) {
while ( (elem = elem[ dir ]) ) {
if ( elem.nodeType === 1 || checkNonElements ) {
@@ -2132,14 +2231,21 @@ function addCombinator( matcher, combinator, base ) {
while ( (elem = elem[ dir ]) ) {
if ( elem.nodeType === 1 || checkNonElements ) {
outerCache = elem[ expando ] || (elem[ expando ] = {});
- if ( (oldCache = outerCache[ dir ]) &&
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
+
+ if ( skip && skip === elem.nodeName.toLowerCase() ) {
+ elem = elem[ dir ] || elem;
+ } else if ( (oldCache = uniqueCache[ key ]) &&
oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
// Assign to newCache so results back-propagate to previous elements
return (newCache[ 2 ] = oldCache[ 2 ]);
} else {
// Reuse newcache so results back-propagate to previous elements
- outerCache[ dir ] = newCache;
+ uniqueCache[ key ] = newCache;
// A match means we're done; a fail means we have to keep checking
if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
@@ -2266,7 +2372,7 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS
i = matcherOut.length;
while ( i-- ) {
if ( (elem = matcherOut[i]) &&
- (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
+ (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
seed[temp] = !(results[temp] = elem);
}
@@ -2301,13 +2407,16 @@ function matcherFromTokens( tokens ) {
return elem === checkContext;
}, implicitRelative, true ),
matchAnyContext = addCombinator( function( elem ) {
- return indexOf.call( checkContext, elem ) > -1;
+ return indexOf( checkContext, elem ) > -1;
}, implicitRelative, true ),
matchers = [ function( elem, context, xml ) {
- return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
(checkContext = context).nodeType ?
matchContext( elem, context, xml ) :
matchAnyContext( elem, context, xml ) );
+ // Avoid hanging onto element (issue #299)
+ checkContext = null;
+ return ret;
} ];
for ( ; i < len; i++ ) {
@@ -2361,18 +2470,21 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
len = elems.length;
if ( outermost ) {
- outermostContext = context !== document && context;
+ outermostContext = context === document || context || outermost;
}
// Add elements passing elementMatchers directly to results
- // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
// Support: IE<9, Safari
// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
if ( byElement && elem ) {
j = 0;
+ if ( !context && elem.ownerDocument !== document ) {
+ setDocument( elem );
+ xml = !documentIsHTML;
+ }
while ( (matcher = elementMatchers[j++]) ) {
- if ( matcher( elem, context, xml ) ) {
+ if ( matcher( elem, context || document, xml) ) {
results.push( elem );
break;
}
@@ -2396,8 +2508,17 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
}
}
- // Apply set filters to unmatched elements
+ // `i` is now the count of elements visited above, and adding it to `matchedCount`
+ // makes the latter nonnegative.
matchedCount += i;
+
+ // Apply set filters to unmatched elements
+ // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
+ // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
+ // no element matchers and no seed.
+ // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
+ // case, which will result in a "00" `matchedCount` that differs from `i` but is also
+ // numerically zero.
if ( bySet && i !== matchedCount ) {
j = 0;
while ( (matcher = setMatchers[j++]) ) {
@@ -2489,10 +2610,11 @@ select = Sizzle.select = function( selector, context, results, seed ) {
results = results || [];
- // Try to minimize operations if there is no seed and only one group
+ // Try to minimize operations if there is only one selector in the list and no seed
+ // (the latter of which guarantees us context)
if ( match.length === 1 ) {
- // Take a shortcut and set the context if the root selector is an ID
+ // Reduce context if the leading compound selector is an ID
tokens = match[0] = match[0].slice( 0 );
if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
support.getById && context.nodeType === 9 && documentIsHTML &&
@@ -2547,7 +2669,7 @@ select = Sizzle.select = function( selector, context, results, seed ) {
context,
!documentIsHTML,
results,
- rsibling.test( selector ) && testContext( context.parentNode ) || context
+ !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
);
return results;
};
@@ -2557,7 +2679,7 @@ select = Sizzle.select = function( selector, context, results, seed ) {
// Sort stability
support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
-// Support: Chrome<14
+// Support: Chrome 14-35+
// Always assume duplicates if they aren't passed to the comparison function
support.detectDuplicates = !!hasDuplicate;
@@ -2566,17 +2688,17 @@ setDocument();
// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
// Detached nodes confoundingly follow *each other*
-support.sortDetached = assert(function( div1 ) {
+support.sortDetached = assert(function( el ) {
// Should return 1, but returns 4 (following)
- return div1.compareDocumentPosition( document.createElement("div") ) & 1;
+ return el.compareDocumentPosition( document.createElement("fieldset") ) & 1;
});
// Support: IE<8
// Prevent attribute/property "interpolation"
-// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
-if ( !assert(function( div ) {
- div.innerHTML = "<a href='#'></a>";
- return div.firstChild.getAttribute("href") === "#" ;
+// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( el ) {
+ el.innerHTML = "<a href='#'></a>";
+ return el.firstChild.getAttribute("href") === "#" ;
}) ) {
addHandle( "type|href|height|width", function( elem, name, isXML ) {
if ( !isXML ) {
@@ -2587,10 +2709,10 @@ if ( !assert(function( div ) {
// Support: IE<9
// Use defaultValue in place of getAttribute("value")
-if ( !support.attributes || !assert(function( div ) {
- div.innerHTML = "<input/>";
- div.firstChild.setAttribute( "value", "" );
- return div.firstChild.getAttribute( "value" ) === "";
+if ( !support.attributes || !assert(function( el ) {
+ el.innerHTML = "<input/>";
+ el.firstChild.setAttribute( "value", "" );
+ return el.firstChild.getAttribute( "value" ) === "";
}) ) {
addHandle( "value", function( elem, name, isXML ) {
if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
@@ -2601,8 +2723,8 @@ if ( !support.attributes || !assert(function( div ) {
// Support: IE<9
// Use getAttributeNode to fetch booleans when getAttribute lies
-if ( !assert(function( div ) {
- return div.getAttribute("disabled") == null;
+if ( !assert(function( el ) {
+ return el.getAttribute("disabled") == null;
}) ) {
addHandle( booleans, function( elem, name, isXML ) {
var val;
@@ -2623,17 +2745,50 @@ return Sizzle;
jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
-jQuery.expr[":"] = jQuery.expr.pseudos;
-jQuery.unique = Sizzle.uniqueSort;
+
+// Deprecated
+jQuery.expr[ ":" ] = jQuery.expr.pseudos;
+jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
jQuery.text = Sizzle.getText;
jQuery.isXMLDoc = Sizzle.isXML;
jQuery.contains = Sizzle.contains;
+jQuery.escapeSelector = Sizzle.escape;
+
+
+var dir = function( elem, dir, until ) {
+ var matched = [],
+ truncate = until !== undefined;
+
+ while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
+ if ( elem.nodeType === 1 ) {
+ if ( truncate && jQuery( elem ).is( until ) ) {
+ break;
+ }
+ matched.push( elem );
+ }
+ }
+ return matched;
+};
+
+
+var siblings = function( n, elem ) {
+ var matched = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ matched.push( n );
+ }
+ }
+
+ return matched;
+};
+
var rneedsContext = jQuery.expr.match.needsContext;
-var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
+var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
@@ -2643,16 +2798,15 @@ var risSimple = /^.[^:#\[\.,]*$/;
function winnow( elements, qualifier, not ) {
if ( jQuery.isFunction( qualifier ) ) {
return jQuery.grep( elements, function( elem, i ) {
- /* jshint -W018 */
return !!qualifier.call( elem, i, elem ) !== not;
- });
+ } );
}
if ( qualifier.nodeType ) {
return jQuery.grep( elements, function( elem ) {
return ( elem === qualifier ) !== not;
- });
+ } );
}
@@ -2665,8 +2819,8 @@ function winnow( elements, qualifier, not ) {
}
return jQuery.grep( elements, function( elem ) {
- return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
- });
+ return ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1;
+ } );
}
jQuery.filter = function( expr, elems, not ) {
@@ -2680,40 +2834,38 @@ jQuery.filter = function( expr, elems, not ) {
jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
return elem.nodeType === 1;
- }));
+ } ) );
};
-jQuery.fn.extend({
+jQuery.fn.extend( {
find: function( selector ) {
- var i,
- ret = [],
- self = this,
- len = self.length;
+ var i, ret,
+ len = this.length,
+ self = this;
if ( typeof selector !== "string" ) {
- return this.pushStack( jQuery( selector ).filter(function() {
+ return this.pushStack( jQuery( selector ).filter( function() {
for ( i = 0; i < len; i++ ) {
if ( jQuery.contains( self[ i ], this ) ) {
return true;
}
}
- }) );
+ } ) );
}
+ ret = this.pushStack( [] );
+
for ( i = 0; i < len; i++ ) {
jQuery.find( selector, self[ i ], ret );
}
- // Needed because $( selector, context ) becomes $( context ).find( selector )
- ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
- ret.selector = this.selector ? this.selector + " " + selector : selector;
- return ret;
+ return len > 1 ? jQuery.uniqueSort( ret ) : ret;
},
filter: function( selector ) {
- return this.pushStack( winnow(this, selector || [], false) );
+ return this.pushStack( winnow( this, selector || [], false ) );
},
not: function( selector ) {
- return this.pushStack( winnow(this, selector || [], true) );
+ return this.pushStack( winnow( this, selector || [], true ) );
},
is: function( selector ) {
return !!winnow(
@@ -2727,7 +2879,7 @@ jQuery.fn.extend({
false
).length;
}
-});
+} );
// Initialize a jQuery object
@@ -2736,15 +2888,13 @@ jQuery.fn.extend({
// A central reference to the root jQuery(document)
var rootjQuery,
- // Use the correct document accordingly with window argument (sandbox)
- document = window.document,
-
// A simple way to check for HTML strings
// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
// Strict HTML recognition (#11290: must start with <)
- rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+ // Shortcut simple #id case for speed
+ rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
- init = jQuery.fn.init = function( selector, context ) {
+ init = jQuery.fn.init = function( selector, context, root ) {
var match, elem;
// HANDLE: $(""), $(null), $(undefined), $(false)
@@ -2752,9 +2902,16 @@ var rootjQuery,
return this;
}
+ // Method init() accepts an alternate rootjQuery
+ // so migrate can support jQuery.sub (gh-2101)
+ root = root || rootjQuery;
+
// Handle HTML strings
if ( typeof selector === "string" ) {
- if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ if ( selector[ 0 ] === "<" &&
+ selector[ selector.length - 1 ] === ">" &&
+ selector.length >= 3 ) {
+
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [ null, selector, null ];
@@ -2763,23 +2920,24 @@ var rootjQuery,
}
// Match html or make sure no context is specified for #id
- if ( match && (match[1] || !context) ) {
+ if ( match && ( match[ 1 ] || !context ) ) {
// HANDLE: $(html) -> $(array)
- if ( match[1] ) {
- context = context instanceof jQuery ? context[0] : context;
+ if ( match[ 1 ] ) {
+ context = context instanceof jQuery ? context[ 0 ] : context;
- // scripts is true for back-compat
+ // Option to run scripts is true for back-compat
// Intentionally let the error be thrown if parseHTML is not present
jQuery.merge( this, jQuery.parseHTML(
- match[1],
+ match[ 1 ],
context && context.nodeType ? context.ownerDocument || context : document,
true
) );
// HANDLE: $(html, props)
- if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+ if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
for ( match in context ) {
+
// Properties of context are called as methods if possible
if ( jQuery.isFunction( this[ match ] ) ) {
this[ match ]( context[ match ] );
@@ -2795,30 +2953,20 @@ var rootjQuery,
// HANDLE: $(#id)
} else {
- elem = document.getElementById( match[2] );
-
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document #6963
- if ( elem && elem.parentNode ) {
- // Handle the case where IE and Opera return items
- // by name instead of ID
- if ( elem.id !== match[2] ) {
- return rootjQuery.find( selector );
- }
+ elem = document.getElementById( match[ 2 ] );
+
+ if ( elem ) {
- // Otherwise, we inject the element directly into the jQuery object
+ // Inject the element directly into the jQuery object
+ this[ 0 ] = elem;
this.length = 1;
- this[0] = elem;
}
-
- this.context = document;
- this.selector = selector;
return this;
}
// HANDLE: $(expr, $(...))
} else if ( !context || context.jquery ) {
- return ( context || rootjQuery ).find( selector );
+ return ( context || root ).find( selector );
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
@@ -2828,24 +2976,20 @@ var rootjQuery,
// HANDLE: $(DOMElement)
} else if ( selector.nodeType ) {
- this.context = this[0] = selector;
+ this[ 0 ] = selector;
this.length = 1;
return this;
// HANDLE: $(function)
// Shortcut for document ready
} else if ( jQuery.isFunction( selector ) ) {
- return typeof rootjQuery.ready !== "undefined" ?
- rootjQuery.ready( selector ) :
+ return root.ready !== undefined ?
+ root.ready( selector ) :
+
// Execute immediately if ready is not present
selector( jQuery );
}
- if ( selector.selector !== undefined ) {
- this.selector = selector.selector;
- this.context = selector.context;
- }
-
return jQuery.makeArray( selector, this );
};
@@ -2857,7 +3001,8 @@ rootjQuery = jQuery( document );
var rparentsprev = /^(?:parents|prev(?:Until|All))/,
- // methods guaranteed to produce a unique set when starting from a unique set
+
+ // Methods guaranteed to produce a unique set when starting from a unique set
guaranteedUnique = {
children: true,
contents: true,
@@ -2865,46 +3010,19 @@ var rparentsprev = /^(?:parents|prev(?:Until|All))/,
prev: true
};
-jQuery.extend({
- dir: function( elem, dir, until ) {
- var matched = [],
- cur = elem[ dir ];
-
- while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
- if ( cur.nodeType === 1 ) {
- matched.push( cur );
- }
- cur = cur[dir];
- }
- return matched;
- },
-
- sibling: function( n, elem ) {
- var r = [];
-
- for ( ; n; n = n.nextSibling ) {
- if ( n.nodeType === 1 && n !== elem ) {
- r.push( n );
- }
- }
-
- return r;
- }
-});
-
-jQuery.fn.extend({
+jQuery.fn.extend( {
has: function( target ) {
- var i,
- targets = jQuery( target, this ),
- len = targets.length;
+ var targets = jQuery( target, this ),
+ l = targets.length;
- return this.filter(function() {
- for ( i = 0; i < len; i++ ) {
- if ( jQuery.contains( this, targets[i] ) ) {
+ return this.filter( function() {
+ var i = 0;
+ for ( ; i < l; i++ ) {
+ if ( jQuery.contains( this, targets[ i ] ) ) {
return true;
}
}
- });
+ } );
},
closest: function( selectors, context ) {
@@ -2912,52 +3030,55 @@ jQuery.fn.extend({
i = 0,
l = this.length,
matched = [],
- pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
- jQuery( selectors, context || this.context ) :
- 0;
+ targets = typeof selectors !== "string" && jQuery( selectors );
- for ( ; i < l; i++ ) {
- for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
- // Always skip document fragments
- if ( cur.nodeType < 11 && (pos ?
- pos.index(cur) > -1 :
+ // Positional selectors never match, since there's no _selection_ context
+ if ( !rneedsContext.test( selectors ) ) {
+ for ( ; i < l; i++ ) {
+ for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
- // Don't pass non-elements to Sizzle
- cur.nodeType === 1 &&
- jQuery.find.matchesSelector(cur, selectors)) ) {
+ // Always skip document fragments
+ if ( cur.nodeType < 11 && ( targets ?
+ targets.index( cur ) > -1 :
- matched.push( cur );
- break;
+ // Don't pass non-elements to Sizzle
+ cur.nodeType === 1 &&
+ jQuery.find.matchesSelector( cur, selectors ) ) ) {
+
+ matched.push( cur );
+ break;
+ }
}
}
}
- return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
+ return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
},
- // Determine the position of an element within
- // the matched set of elements
+ // Determine the position of an element within the set
index: function( elem ) {
// No argument, return index in parent
if ( !elem ) {
- return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
+ return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
}
- // index in selector
+ // Index in selector
if ( typeof elem === "string" ) {
- return jQuery.inArray( this[0], jQuery( elem ) );
+ return indexOf.call( jQuery( elem ), this[ 0 ] );
}
// Locate the position of the desired element
- return jQuery.inArray(
+ return indexOf.call( this,
+
// If it receives a jQuery object, the first element is used
- elem.jquery ? elem[0] : elem, this );
+ elem.jquery ? elem[ 0 ] : elem
+ );
},
add: function( selector, context ) {
return this.pushStack(
- jQuery.unique(
+ jQuery.uniqueSort(
jQuery.merge( this.get(), jQuery( selector, context ) )
)
);
@@ -2965,29 +3086,26 @@ jQuery.fn.extend({
addBack: function( selector ) {
return this.add( selector == null ?
- this.prevObject : this.prevObject.filter(selector)
+ this.prevObject : this.prevObject.filter( selector )
);
}
-});
+} );
function sibling( cur, dir ) {
- do {
- cur = cur[ dir ];
- } while ( cur && cur.nodeType !== 1 );
-
+ while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
return cur;
}
-jQuery.each({
+jQuery.each( {
parent: function( elem ) {
var parent = elem.parentNode;
return parent && parent.nodeType !== 11 ? parent : null;
},
parents: function( elem ) {
- return jQuery.dir( elem, "parentNode" );
+ return dir( elem, "parentNode" );
},
parentsUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "parentNode", until );
+ return dir( elem, "parentNode", until );
},
next: function( elem ) {
return sibling( elem, "nextSibling" );
@@ -2996,68 +3114,64 @@ jQuery.each({
return sibling( elem, "previousSibling" );
},
nextAll: function( elem ) {
- return jQuery.dir( elem, "nextSibling" );
+ return dir( elem, "nextSibling" );
},
prevAll: function( elem ) {
- return jQuery.dir( elem, "previousSibling" );
+ return dir( elem, "previousSibling" );
},
nextUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "nextSibling", until );
+ return dir( elem, "nextSibling", until );
},
prevUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "previousSibling", until );
+ return dir( elem, "previousSibling", until );
},
siblings: function( elem ) {
- return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+ return siblings( ( elem.parentNode || {} ).firstChild, elem );
},
children: function( elem ) {
- return jQuery.sibling( elem.firstChild );
+ return siblings( elem.firstChild );
},
contents: function( elem ) {
- return jQuery.nodeName( elem, "iframe" ) ?
- elem.contentDocument || elem.contentWindow.document :
- jQuery.merge( [], elem.childNodes );
+ return elem.contentDocument || jQuery.merge( [], elem.childNodes );
}
}, function( name, fn ) {
jQuery.fn[ name ] = function( until, selector ) {
- var ret = jQuery.map( this, fn, until );
+ var matched = jQuery.map( this, fn, until );
if ( name.slice( -5 ) !== "Until" ) {
selector = until;
}
if ( selector && typeof selector === "string" ) {
- ret = jQuery.filter( selector, ret );
+ matched = jQuery.filter( selector, matched );
}
if ( this.length > 1 ) {
+
// Remove duplicates
if ( !guaranteedUnique[ name ] ) {
- ret = jQuery.unique( ret );
+ jQuery.uniqueSort( matched );
}
// Reverse order for parents* and prev-derivatives
if ( rparentsprev.test( name ) ) {
- ret = ret.reverse();
+ matched.reverse();
}
}
- return this.pushStack( ret );
+ return this.pushStack( matched );
};
-});
-var rnotwhite = (/\S+/g);
-
+} );
+var rnotwhite = ( /\S+/g );
-// String to Object options format cache
-var optionsCache = {};
-// Convert String-formatted options into Object-formatted ones and store in cache
+// Convert String-formatted options into Object-formatted ones
function createOptions( options ) {
- var object = optionsCache[ options ] = {};
+ var object = {};
jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
object[ flag ] = true;
- });
+ } );
return object;
}
@@ -3088,156 +3202,186 @@ jQuery.Callbacks = function( options ) {
// Convert options from String-formatted to Object-formatted if needed
// (we check in cache first)
options = typeof options === "string" ?
- ( optionsCache[ options ] || createOptions( options ) ) :
+ createOptions( options ) :
jQuery.extend( {}, options );
var // Flag to know if list is currently firing
firing,
- // Last fire value (for non-forgettable lists)
+
+ // Last fire value for non-forgettable lists
memory,
+
// Flag to know if list was already fired
fired,
- // End of the loop when firing
- firingLength,
- // Index of currently firing callback (modified by remove if needed)
- firingIndex,
- // First callback to fire (used internally by add and fireWith)
- firingStart,
+
+ // Flag to prevent firing
+ locked,
+
// Actual callback list
list = [],
- // Stack of fire calls for repeatable lists
- stack = !options.once && [],
+
+ // Queue of execution data for repeatable lists
+ queue = [],
+
+ // Index of currently firing callback (modified by add/remove as needed)
+ firingIndex = -1,
+
// Fire callbacks
- fire = function( data ) {
- memory = options.memory && data;
- fired = true;
- firingIndex = firingStart || 0;
- firingStart = 0;
- firingLength = list.length;
- firing = true;
- for ( ; list && firingIndex < firingLength; firingIndex++ ) {
- if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
- memory = false; // To prevent further calls using add
- break;
+ fire = function() {
+
+ // Enforce single-firing
+ locked = options.once;
+
+ // Execute callbacks for all pending executions,
+ // respecting firingIndex overrides and runtime changes
+ fired = firing = true;
+ for ( ; queue.length; firingIndex = -1 ) {
+ memory = queue.shift();
+ while ( ++firingIndex < list.length ) {
+
+ // Run callback and check for early termination
+ if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
+ options.stopOnFalse ) {
+
+ // Jump to end and forget the data so .add doesn't re-fire
+ firingIndex = list.length;
+ memory = false;
+ }
}
}
+
+ // Forget the data if we're done with it
+ if ( !options.memory ) {
+ memory = false;
+ }
+
firing = false;
- if ( list ) {
- if ( stack ) {
- if ( stack.length ) {
- fire( stack.shift() );
- }
- } else if ( memory ) {
+
+ // Clean up if we're done firing for good
+ if ( locked ) {
+
+ // Keep an empty list if we have data for future add calls
+ if ( memory ) {
list = [];
+
+ // Otherwise, this object is spent
} else {
- self.disable();
+ list = "";
}
}
},
+
// Actual Callbacks object
self = {
+
// Add a callback or a collection of callbacks to the list
add: function() {
if ( list ) {
- // First, we save the current length
- var start = list.length;
- (function add( args ) {
+
+ // If we have memory from a past run, we should fire after adding
+ if ( memory && !firing ) {
+ firingIndex = list.length - 1;
+ queue.push( memory );
+ }
+
+ ( function add( args ) {
jQuery.each( args, function( _, arg ) {
- var type = jQuery.type( arg );
- if ( type === "function" ) {
+ if ( jQuery.isFunction( arg ) ) {
if ( !options.unique || !self.has( arg ) ) {
list.push( arg );
}
- } else if ( arg && arg.length && type !== "string" ) {
+ } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
+
// Inspect recursively
add( arg );
}
- });
- })( arguments );
- // Do we need to add the callbacks to the
- // current firing batch?
- if ( firing ) {
- firingLength = list.length;
- // With memory, if we're not firing then
- // we should call right away
- } else if ( memory ) {
- firingStart = start;
- fire( memory );
+ } );
+ } )( arguments );
+
+ if ( memory && !firing ) {
+ fire();
}
}
return this;
},
+
// Remove a callback from the list
remove: function() {
- if ( list ) {
- jQuery.each( arguments, function( _, arg ) {
- var index;
- while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
- list.splice( index, 1 );
- // Handle firing indexes
- if ( firing ) {
- if ( index <= firingLength ) {
- firingLength--;
- }
- if ( index <= firingIndex ) {
- firingIndex--;
- }
- }
+ jQuery.each( arguments, function( _, arg ) {
+ var index;
+ while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+ list.splice( index, 1 );
+
+ // Handle firing indexes
+ if ( index <= firingIndex ) {
+ firingIndex--;
}
- });
- }
+ }
+ } );
return this;
},
+
// Check if a given callback is in the list.
// If no argument is given, return whether or not list has callbacks attached.
has: function( fn ) {
- return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+ return fn ?
+ jQuery.inArray( fn, list ) > -1 :
+ list.length > 0;
},
+
// Remove all callbacks from the list
empty: function() {
- list = [];
- firingLength = 0;
+ if ( list ) {
+ list = [];
+ }
return this;
},
- // Have the list do nothing anymore
+
+ // Disable .fire and .add
+ // Abort any current/pending executions
+ // Clear all callbacks and values
disable: function() {
- list = stack = memory = undefined;
+ locked = queue = [];
+ list = memory = "";
return this;
},
- // Is it disabled?
disabled: function() {
return !list;
},
- // Lock the list in its current state
+
+ // Disable .fire
+ // Also disable .add unless we have memory (since it would have no effect)
+ // Abort any pending executions
lock: function() {
- stack = undefined;
- if ( !memory ) {
- self.disable();
+ locked = queue = [];
+ if ( !memory && !firing ) {
+ list = memory = "";
}
return this;
},
- // Is it locked?
locked: function() {
- return !stack;
+ return !!locked;
},
+
// Call all callbacks with the given context and arguments
fireWith: function( context, args ) {
- if ( list && ( !fired || stack ) ) {
+ if ( !locked ) {
args = args || [];
args = [ context, args.slice ? args.slice() : args ];
- if ( firing ) {
- stack.push( args );
- } else {
- fire( args );
+ queue.push( args );
+ if ( !firing ) {
+ fire();
}
}
return this;
},
+
// Call all the callbacks with the given arguments
fire: function() {
self.fireWith( this, arguments );
return this;
},
+
// To know if the callbacks have already been called at least once
fired: function() {
return !!fired;
@@ -3248,14 +3392,58 @@ jQuery.Callbacks = function( options ) {
};
-jQuery.extend({
+function Identity( v ) {
+ return v;
+}
+function Thrower( ex ) {
+ throw ex;
+}
+
+function adoptValue( value, resolve, reject ) {
+ var method;
+
+ try {
+
+ // Check for promise aspect first to privilege synchronous behavior
+ if ( value && jQuery.isFunction( ( method = value.promise ) ) ) {
+ method.call( value ).done( resolve ).fail( reject );
+
+ // Other thenables
+ } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) {
+ method.call( value, resolve, reject );
+
+ // Other non-thenables
+ } else {
+
+ // Support: Android 4.0 only
+ // Strict mode functions invoked without .call/.apply get global-object context
+ resolve.call( undefined, value );
+ }
+
+ // For Promises/A+, convert exceptions into rejections
+ // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
+ // Deferred#then to conditionally suppress rejection.
+ } catch ( value ) {
+
+ // Support: Android 4.0 only
+ // Strict mode functions invoked without .call/.apply get global-object context
+ reject.call( undefined, value );
+ }
+}
+
+jQuery.extend( {
Deferred: function( func ) {
var tuples = [
- // action, add listener, listener list, final state
- [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
- [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
- [ "notify", "progress", jQuery.Callbacks("memory") ]
+
+ // action, add listener, callbacks,
+ // ... .then handlers, argument index, [final state]
+ [ "notify", "progress", jQuery.Callbacks( "memory" ),
+ jQuery.Callbacks( "memory" ), 2 ],
+ [ "resolve", "done", jQuery.Callbacks( "once memory" ),
+ jQuery.Callbacks( "once memory" ), 0, "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks( "once memory" ),
+ jQuery.Callbacks( "once memory" ), 1, "rejected" ]
],
state = "pending",
promise = {
@@ -3266,27 +3454,206 @@ jQuery.extend({
deferred.done( arguments ).fail( arguments );
return this;
},
- then: function( /* fnDone, fnFail, fnProgress */ ) {
+ "catch": function( fn ) {
+ return promise.then( null, fn );
+ },
+
+ // Keep pipe for back-compat
+ pipe: function( /* fnDone, fnFail, fnProgress */ ) {
var fns = arguments;
- return jQuery.Deferred(function( newDefer ) {
+
+ return jQuery.Deferred( function( newDefer ) {
jQuery.each( tuples, function( i, tuple ) {
- var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
- // deferred[ done | fail | progress ] for forwarding actions to newDefer
- deferred[ tuple[1] ](function() {
+
+ // Map tuples (progress, done, fail) to arguments (done, fail, progress)
+ var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
+
+ // deferred.progress(function() { bind to newDefer or newDefer.notify })
+ // deferred.done(function() { bind to newDefer or newDefer.resolve })
+ // deferred.fail(function() { bind to newDefer or newDefer.reject })
+ deferred[ tuple[ 1 ] ]( function() {
var returned = fn && fn.apply( this, arguments );
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise()
+ .progress( newDefer.notify )
.done( newDefer.resolve )
- .fail( newDefer.reject )
- .progress( newDefer.notify );
+ .fail( newDefer.reject );
} else {
- newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+ newDefer[ tuple[ 0 ] + "With" ](
+ this,
+ fn ? [ returned ] : arguments
+ );
}
- });
- });
+ } );
+ } );
fns = null;
- }).promise();
+ } ).promise();
},
+ then: function( onFulfilled, onRejected, onProgress ) {
+ var maxDepth = 0;
+ function resolve( depth, deferred, handler, special ) {
+ return function() {
+ var that = this,
+ args = arguments,
+ mightThrow = function() {
+ var returned, then;
+
+ // Support: Promises/A+ section 2.3.3.3.3
+ // https://promisesaplus.com/#point-59
+ // Ignore double-resolution attempts
+ if ( depth < maxDepth ) {
+ return;
+ }
+
+ returned = handler.apply( that, args );
+
+ // Support: Promises/A+ section 2.3.1
+ // https://promisesaplus.com/#point-48
+ if ( returned === deferred.promise() ) {
+ throw new TypeError( "Thenable self-resolution" );
+ }
+
+ // Support: Promises/A+ sections 2.3.3.1, 3.5
+ // https://promisesaplus.com/#point-54
+ // https://promisesaplus.com/#point-75
+ // Retrieve `then` only once
+ then = returned &&
+
+ // Support: Promises/A+ section 2.3.4
+ // https://promisesaplus.com/#point-64
+ // Only check objects and functions for thenability
+ ( typeof returned === "object" ||
+ typeof returned === "function" ) &&
+ returned.then;
+
+ // Handle a returned thenable
+ if ( jQuery.isFunction( then ) ) {
+
+ // Special processors (notify) just wait for resolution
+ if ( special ) {
+ then.call(
+ returned,
+ resolve( maxDepth, deferred, Identity, special ),
+ resolve( maxDepth, deferred, Thrower, special )
+ );
+
+ // Normal processors (resolve) also hook into progress
+ } else {
+
+ // ...and disregard older resolution values
+ maxDepth++;
+
+ then.call(
+ returned,
+ resolve( maxDepth, deferred, Identity, special ),
+ resolve( maxDepth, deferred, Thrower, special ),
+ resolve( maxDepth, deferred, Identity,
+ deferred.notifyWith )
+ );
+ }
+
+ // Handle all other returned values
+ } else {
+
+ // Only substitute handlers pass on context
+ // and multiple values (non-spec behavior)
+ if ( handler !== Identity ) {
+ that = undefined;
+ args = [ returned ];
+ }
+
+ // Process the value(s)
+ // Default process is resolve
+ ( special || deferred.resolveWith )( that, args );
+ }
+ },
+
+ // Only normal processors (resolve) catch and reject exceptions
+ process = special ?
+ mightThrow :
+ function() {
+ try {
+ mightThrow();
+ } catch ( e ) {
+
+ if ( jQuery.Deferred.exceptionHook ) {
+ jQuery.Deferred.exceptionHook( e,
+ process.stackTrace );
+ }
+
+ // Support: Promises/A+ section 2.3.3.3.4.1
+ // https://promisesaplus.com/#point-61
+ // Ignore post-resolution exceptions
+ if ( depth + 1 >= maxDepth ) {
+
+ // Only substitute handlers pass on context
+ // and multiple values (non-spec behavior)
+ if ( handler !== Thrower ) {
+ that = undefined;
+ args = [ e ];
+ }
+
+ deferred.rejectWith( that, args );
+ }
+ }
+ };
+
+ // Support: Promises/A+ section 2.3.3.3.1
+ // https://promisesaplus.com/#point-57
+ // Re-resolve promises immediately to dodge false rejection from
+ // subsequent errors
+ if ( depth ) {
+ process();
+ } else {
+
+ // Call an optional hook to record the stack, in case of exception
+ // since it's otherwise lost when execution goes async
+ if ( jQuery.Deferred.getStackHook ) {
+ process.stackTrace = jQuery.Deferred.getStackHook();
+ }
+ window.setTimeout( process );
+ }
+ };
+ }
+
+ return jQuery.Deferred( function( newDefer ) {
+
+ // progress_handlers.add( ... )
+ tuples[ 0 ][ 3 ].add(
+ resolve(
+ 0,
+ newDefer,
+ jQuery.isFunction( onProgress ) ?
+ onProgress :
+ Identity,
+ newDefer.notifyWith
+ )
+ );
+
+ // fulfilled_handlers.add( ... )
+ tuples[ 1 ][ 3 ].add(
+ resolve(
+ 0,
+ newDefer,
+ jQuery.isFunction( onFulfilled ) ?
+ onFulfilled :
+ Identity
+ )
+ );
+
+ // rejected_handlers.add( ... )
+ tuples[ 2 ][ 3 ].add(
+ resolve(
+ 0,
+ newDefer,
+ jQuery.isFunction( onRejected ) ?
+ onRejected :
+ Thrower
+ )
+ );
+ } ).promise();
+ },
+
// Get a promise for this deferred
// If obj is provided, the promise aspect is added to the object
promise: function( obj ) {
@@ -3295,34 +3662,53 @@ jQuery.extend({
},
deferred = {};
- // Keep pipe for back-compat
- promise.pipe = promise.then;
-
// Add list-specific methods
jQuery.each( tuples, function( i, tuple ) {
var list = tuple[ 2 ],
- stateString = tuple[ 3 ];
+ stateString = tuple[ 5 ];
- // promise[ done | fail | progress ] = list.add
- promise[ tuple[1] ] = list.add;
+ // promise.progress = list.add
+ // promise.done = list.add
+ // promise.fail = list.add
+ promise[ tuple[ 1 ] ] = list.add;
// Handle state
if ( stateString ) {
- list.add(function() {
- // state = [ resolved | rejected ]
- state = stateString;
+ list.add(
+ function() {
+
+ // state = "resolved" (i.e., fulfilled)
+ // state = "rejected"
+ state = stateString;
+ },
- // [ reject_list | resolve_list ].disable; progress_list.lock
- }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+ // rejected_callbacks.disable
+ // fulfilled_callbacks.disable
+ tuples[ 3 - i ][ 2 ].disable,
+
+ // progress_callbacks.lock
+ tuples[ 0 ][ 2 ].lock
+ );
}
- // deferred[ resolve | reject | notify ]
- deferred[ tuple[0] ] = function() {
- deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
+ // progress_handlers.fire
+ // fulfilled_handlers.fire
+ // rejected_handlers.fire
+ list.add( tuple[ 3 ].fire );
+
+ // deferred.notify = function() { deferred.notifyWith(...) }
+ // deferred.resolve = function() { deferred.resolveWith(...) }
+ // deferred.reject = function() { deferred.rejectWith(...) }
+ deferred[ tuple[ 0 ] ] = function() {
+ deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
return this;
};
- deferred[ tuple[0] + "With" ] = list.fireWith;
- });
+
+ // deferred.notifyWith = list.fireWith
+ // deferred.resolveWith = list.fireWith
+ // deferred.rejectWith = list.fireWith
+ deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
+ } );
// Make the deferred a promise
promise.promise( deferred );
@@ -3337,71 +3723,100 @@ jQuery.extend({
},
// Deferred helper
- when: function( subordinate /* , ..., subordinateN */ ) {
- var i = 0,
- resolveValues = slice.call( arguments ),
- length = resolveValues.length,
+ when: function( singleValue ) {
+ var
- // the count of uncompleted subordinates
- remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+ // count of uncompleted subordinates
+ remaining = arguments.length,
- // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
- deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+ // count of unprocessed arguments
+ i = remaining,
- // Update function for both resolve and progress values
- updateFunc = function( i, contexts, values ) {
- return function( value ) {
- contexts[ i ] = this;
- values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
- if ( values === progressValues ) {
- deferred.notifyWith( contexts, values );
+ // subordinate fulfillment data
+ resolveContexts = Array( i ),
+ resolveValues = slice.call( arguments ),
- } else if ( !(--remaining) ) {
- deferred.resolveWith( contexts, values );
+ // the master Deferred
+ master = jQuery.Deferred(),
+
+ // subordinate callback factory
+ updateFunc = function( i ) {
+ return function( value ) {
+ resolveContexts[ i ] = this;
+ resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+ if ( !( --remaining ) ) {
+ master.resolveWith( resolveContexts, resolveValues );
}
};
- },
+ };
- progressValues, progressContexts, resolveContexts;
+ // Single- and empty arguments are adopted like Promise.resolve
+ if ( remaining <= 1 ) {
+ adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject );
- // add listeners to Deferred subordinates; treat others as resolved
- if ( length > 1 ) {
- progressValues = new Array( length );
- progressContexts = new Array( length );
- resolveContexts = new Array( length );
- for ( ; i < length; i++ ) {
- if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
- resolveValues[ i ].promise()
- .done( updateFunc( i, resolveContexts, resolveValues ) )
- .fail( deferred.reject )
- .progress( updateFunc( i, progressContexts, progressValues ) );
- } else {
- --remaining;
- }
+ // Use .then() to unwrap secondary thenables (cf. gh-3000)
+ if ( master.state() === "pending" ||
+ jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
+
+ return master.then();
}
}
- // if we're not waiting on anything, resolve the master
- if ( !remaining ) {
- deferred.resolveWith( resolveContexts, resolveValues );
+ // Multiple arguments are aggregated like Promise.all array elements
+ while ( i-- ) {
+ adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
}
- return deferred.promise();
+ return master.promise();
}
-});
+} );
+
+
+// These usually indicate a programmer mistake during development,
+// warn about them ASAP rather than swallowing them by default.
+var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
+
+jQuery.Deferred.exceptionHook = function( error, stack ) {
+
+ // Support: IE 8 - 9 only
+ // Console exists when dev tools are open, which can happen at any time
+ if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
+ window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
+ }
+};
+
+
+
+
+jQuery.readyException = function( error ) {
+ window.setTimeout( function() {
+ throw error;
+ } );
+};
+
+
// The deferred used on DOM ready
-var readyList;
+var readyList = jQuery.Deferred();
jQuery.fn.ready = function( fn ) {
- // Add the callback
- jQuery.ready.promise().done( fn );
+
+ readyList
+ .then( fn )
+
+ // Wrap jQuery.readyException in a function so that the lookup
+ // happens at the time of error handling instead of callback
+ // registration.
+ .catch( function( error ) {
+ jQuery.readyException( error );
+ } );
return this;
};
-jQuery.extend({
+jQuery.extend( {
+
// Is the DOM ready to be used? Set to true once it occurs.
isReady: false,
@@ -3426,11 +3841,6 @@ jQuery.extend({
return;
}
- // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
- if ( !document.body ) {
- return setTimeout( jQuery.ready );
- }
-
// Remember that the DOM is ready
jQuery.isReady = true;
@@ -3441,486 +3851,360 @@ jQuery.extend({
// If there are functions bound, to execute
readyList.resolveWith( document, [ jQuery ] );
-
- // Trigger any bound ready events
- if ( jQuery.fn.triggerHandler ) {
- jQuery( document ).triggerHandler( "ready" );
- jQuery( document ).off( "ready" );
- }
}
-});
+} );
-/**
- * Clean-up method for dom ready events
- */
-function detach() {
- if ( document.addEventListener ) {
- document.removeEventListener( "DOMContentLoaded", completed, false );
- window.removeEventListener( "load", completed, false );
-
- } else {
- document.detachEvent( "onreadystatechange", completed );
- window.detachEvent( "onload", completed );
- }
-}
+jQuery.ready.then = readyList.then;
-/**
- * The ready event handler and self cleanup method
- */
+// The ready event handler and self cleanup method
function completed() {
- // readyState === "complete" is good enough for us to call the dom ready in oldIE
- if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
- detach();
- jQuery.ready();
- }
+ document.removeEventListener( "DOMContentLoaded", completed );
+ window.removeEventListener( "load", completed );
+ jQuery.ready();
}
-jQuery.ready.promise = function( obj ) {
- if ( !readyList ) {
-
- readyList = jQuery.Deferred();
+// Catch cases where $(document).ready() is called
+// after the browser event has already occurred.
+// Support: IE <=9 - 10 only
+// Older IE sometimes signals "interactive" too soon
+if ( document.readyState === "complete" ||
+ ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
- // Catch cases where $(document).ready() is called after the browser event has already occurred.
- // we once tried to use readyState "interactive" here, but it caused issues like the one
- // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
- if ( document.readyState === "complete" ) {
- // Handle it asynchronously to allow scripts the opportunity to delay ready
- setTimeout( jQuery.ready );
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ window.setTimeout( jQuery.ready );
- // Standards-based browsers support DOMContentLoaded
- } else if ( document.addEventListener ) {
- // Use the handy event callback
- document.addEventListener( "DOMContentLoaded", completed, false );
+} else {
- // A fallback to window.onload, that will always work
- window.addEventListener( "load", completed, false );
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed );
- // If IE event model is used
- } else {
- // Ensure firing before onload, maybe late but safe also for iframes
- document.attachEvent( "onreadystatechange", completed );
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed );
+}
- // A fallback to window.onload, that will always work
- window.attachEvent( "onload", completed );
- // If IE and not a frame
- // continually check to see if the document is ready
- var top = false;
- try {
- top = window.frameElement == null && document.documentElement;
- } catch(e) {}
- if ( top && top.doScroll ) {
- (function doScrollCheck() {
- if ( !jQuery.isReady ) {
-
- try {
- // Use the trick by Diego Perini
- // http://javascript.nwbox.com/IEContentLoaded/
- top.doScroll("left");
- } catch(e) {
- return setTimeout( doScrollCheck, 50 );
- }
-
- // detach all dom ready events
- detach();
+// Multifunctional method to get and set values of a collection
+// The value/s can optionally be executed if it's a function
+var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+ var i = 0,
+ len = elems.length,
+ bulk = key == null;
- // and execute any waiting functions
- jQuery.ready();
- }
- })();
- }
+ // Sets many values
+ if ( jQuery.type( key ) === "object" ) {
+ chainable = true;
+ for ( i in key ) {
+ access( elems, fn, i, key[ i ], true, emptyGet, raw );
}
- }
- return readyList.promise( obj );
-};
-
-
-var strundefined = typeof undefined;
-
-
-
-// Support: IE<9
-// Iteration over object's inherited properties before its own
-var i;
-for ( i in jQuery( support ) ) {
- break;
-}
-support.ownLast = i !== "0";
-// Note: most support tests are defined in their respective modules.
-// false until the test is run
-support.inlineBlockNeedsLayout = false;
+ // Sets one value
+ } else if ( value !== undefined ) {
+ chainable = true;
-// Execute ASAP in case we need to set body.style.zoom
-jQuery(function() {
- // Minified: var a,b,c,d
- var val, div, body, container;
+ if ( !jQuery.isFunction( value ) ) {
+ raw = true;
+ }
- body = document.getElementsByTagName( "body" )[ 0 ];
- if ( !body || !body.style ) {
- // Return for frameset docs that don't have a body
- return;
- }
+ if ( bulk ) {
- // Setup
- div = document.createElement( "div" );
- container = document.createElement( "div" );
- container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
- body.appendChild( container ).appendChild( div );
+ // Bulk operations run against the entire set
+ if ( raw ) {
+ fn.call( elems, value );
+ fn = null;
- if ( typeof div.style.zoom !== strundefined ) {
- // Support: IE<8
- // Check if natively block-level elements act like inline-block
- // elements when setting their display to 'inline' and giving
- // them layout
- div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
+ // ...except when executing function values
+ } else {
+ bulk = fn;
+ fn = function( elem, key, value ) {
+ return bulk.call( jQuery( elem ), value );
+ };
+ }
+ }
- support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
- if ( val ) {
- // Prevent IE 6 from affecting layout for positioned elements #11048
- // Prevent IE from shrinking the body in IE 7 mode #12869
- // Support: IE<8
- body.style.zoom = 1;
+ if ( fn ) {
+ for ( ; i < len; i++ ) {
+ fn(
+ elems[ i ], key, raw ?
+ value :
+ value.call( elems[ i ], i, fn( elems[ i ], key ) )
+ );
+ }
}
}
- body.removeChild( container );
-});
+ return chainable ?
+ elems :
+ // Gets
+ bulk ?
+ fn.call( elems ) :
+ len ? fn( elems[ 0 ], key ) : emptyGet;
+};
+var acceptData = function( owner ) {
+
+ // Accepts only:
+ // - Node
+ // - Node.ELEMENT_NODE
+ // - Node.DOCUMENT_NODE
+ // - Object
+ // - Any
+ return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
+};
-(function() {
- var div = document.createElement( "div" );
- // Execute the test only if not already executed in another module.
- if (support.deleteExpando == null) {
- // Support: IE<9
- support.deleteExpando = true;
- try {
- delete div.test;
- } catch( e ) {
- support.deleteExpando = false;
- }
- }
+function Data() {
+ this.expando = jQuery.expando + Data.uid++;
+}
- // Null elements to avoid leaks in IE.
- div = null;
-})();
+Data.uid = 1;
+Data.prototype = {
-/**
- * Determines whether an object can have data
- */
-jQuery.acceptData = function( elem ) {
- var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
- nodeType = +elem.nodeType || 1;
+ cache: function( owner ) {
- // Do not set data on non-element DOM nodes because it will not be cleared (#8335).
- return nodeType !== 1 && nodeType !== 9 ?
- false :
+ // Check if the owner object already has a cache
+ var value = owner[ this.expando ];
- // Nodes accept data unless otherwise specified; rejection can be conditional
- !noData || noData !== true && elem.getAttribute("classid") === noData;
-};
+ // If not, create one
+ if ( !value ) {
+ value = {};
+ // We can accept data for non-element nodes in modern browsers,
+ // but we should not, see #8335.
+ // Always return an empty object.
+ if ( acceptData( owner ) ) {
-var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
- rmultiDash = /([A-Z])/g;
+ // If it is a node unlikely to be stringify-ed or looped over
+ // use plain assignment
+ if ( owner.nodeType ) {
+ owner[ this.expando ] = value;
-function dataAttr( elem, key, data ) {
- // If nothing was found internally, try to fetch any
- // data from the HTML5 data-* attribute
- if ( data === undefined && elem.nodeType === 1 ) {
-
- var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+ // Otherwise secure it in a non-enumerable property
+ // configurable must be true to allow the property to be
+ // deleted when data is removed
+ } else {
+ Object.defineProperty( owner, this.expando, {
+ value: value,
+ configurable: true
+ } );
+ }
+ }
+ }
- data = elem.getAttribute( name );
+ return value;
+ },
+ set: function( owner, data, value ) {
+ var prop,
+ cache = this.cache( owner );
+ // Handle: [ owner, key, value ] args
+ // Always use camelCase key (gh-2257)
if ( typeof data === "string" ) {
- try {
- data = data === "true" ? true :
- data === "false" ? false :
- data === "null" ? null :
- // Only convert to a number if it doesn't change the string
- +data + "" === data ? +data :
- rbrace.test( data ) ? jQuery.parseJSON( data ) :
- data;
- } catch( e ) {}
-
- // Make sure we set the data so it isn't changed later
- jQuery.data( elem, key, data );
+ cache[ jQuery.camelCase( data ) ] = value;
+ // Handle: [ owner, { properties } ] args
} else {
- data = undefined;
- }
- }
- return data;
-}
-
-// checks a cache object for emptiness
-function isEmptyDataObject( obj ) {
- var name;
- for ( name in obj ) {
-
- // if the public data object is empty, the private is still empty
- if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
- continue;
- }
- if ( name !== "toJSON" ) {
- return false;
+ // Copy the properties one-by-one to the cache object
+ for ( prop in data ) {
+ cache[ jQuery.camelCase( prop ) ] = data[ prop ];
+ }
}
- }
-
- return true;
-}
-
-function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
- if ( !jQuery.acceptData( elem ) ) {
- return;
- }
-
- var ret, thisCache,
- internalKey = jQuery.expando,
-
- // We have to handle DOM nodes and JS objects differently because IE6-7
- // can't GC object references properly across the DOM-JS boundary
- isNode = elem.nodeType,
-
- // Only DOM nodes need the global jQuery cache; JS object data is
- // attached directly to the object so GC can occur automatically
- cache = isNode ? jQuery.cache : elem,
+ return cache;
+ },
+ get: function( owner, key ) {
+ return key === undefined ?
+ this.cache( owner ) :
- // Only defining an ID for JS objects if its cache already exists allows
- // the code to shortcut on the same path as a DOM node with no cache
- id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+ // Always use camelCase key (gh-2257)
+ owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];
+ },
+ access: function( owner, key, value ) {
- // Avoid doing any more work than we need to when trying to get data on an
- // object that has no data at all
- if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
- return;
- }
+ // In cases where either:
+ //
+ // 1. No key was specified
+ // 2. A string key was specified, but no value provided
+ //
+ // Take the "read" path and allow the get method to determine
+ // which value to return, respectively either:
+ //
+ // 1. The entire cache object
+ // 2. The data stored at the key
+ //
+ if ( key === undefined ||
+ ( ( key && typeof key === "string" ) && value === undefined ) ) {
- if ( !id ) {
- // Only DOM nodes need a new unique ID for each element since their data
- // ends up in the global cache
- if ( isNode ) {
- id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
- } else {
- id = internalKey;
+ return this.get( owner, key );
}
- }
- if ( !cache[ id ] ) {
- // Avoid exposing jQuery metadata on plain JS objects when the object
- // is serialized using JSON.stringify
- cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
- }
+ // When the key is not a string, or both a key and value
+ // are specified, set or extend (existing objects) with either:
+ //
+ // 1. An object of properties
+ // 2. A key and value
+ //
+ this.set( owner, key, value );
- // An object can be passed to jQuery.data instead of a key/value pair; this gets
- // shallow copied over onto the existing cache
- if ( typeof name === "object" || typeof name === "function" ) {
- if ( pvt ) {
- cache[ id ] = jQuery.extend( cache[ id ], name );
- } else {
- cache[ id ].data = jQuery.extend( cache[ id ].data, name );
- }
- }
-
- thisCache = cache[ id ];
+ // Since the "set" path can have two possible entry points
+ // return the expected data based on which path was taken[*]
+ return value !== undefined ? value : key;
+ },
+ remove: function( owner, key ) {
+ var i,
+ cache = owner[ this.expando ];
- // jQuery data() is stored in a separate object inside the object's internal data
- // cache in order to avoid key collisions between internal data and user-defined
- // data.
- if ( !pvt ) {
- if ( !thisCache.data ) {
- thisCache.data = {};
+ if ( cache === undefined ) {
+ return;
}
- thisCache = thisCache.data;
- }
+ if ( key !== undefined ) {
- if ( data !== undefined ) {
- thisCache[ jQuery.camelCase( name ) ] = data;
- }
+ // Support array or space separated string of keys
+ if ( jQuery.isArray( key ) ) {
- // Check for both converted-to-camel and non-converted data property names
- // If a data property was specified
- if ( typeof name === "string" ) {
+ // If key is an array of keys...
+ // We always set camelCase keys, so remove that.
+ key = key.map( jQuery.camelCase );
+ } else {
+ key = jQuery.camelCase( key );
- // First Try to find as-is property data
- ret = thisCache[ name ];
+ // If a key with the spaces exists, use it.
+ // Otherwise, create an array by matching non-whitespace
+ key = key in cache ?
+ [ key ] :
+ ( key.match( rnotwhite ) || [] );
+ }
- // Test for null|undefined property data
- if ( ret == null ) {
+ i = key.length;
- // Try to find the camelCased property
- ret = thisCache[ jQuery.camelCase( name ) ];
+ while ( i-- ) {
+ delete cache[ key[ i ] ];
+ }
}
- } else {
- ret = thisCache;
- }
-
- return ret;
-}
-
-function internalRemoveData( elem, name, pvt ) {
- if ( !jQuery.acceptData( elem ) ) {
- return;
- }
-
- var thisCache, i,
- isNode = elem.nodeType,
- // See jQuery.data for more information
- cache = isNode ? jQuery.cache : elem,
- id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+ // Remove the expando if there's no more data
+ if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
- // If there is already no cache entry for this object, there is no
- // purpose in continuing
- if ( !cache[ id ] ) {
- return;
+ // Support: Chrome <=35 - 45
+ // Webkit & Blink performance suffers when deleting properties
+ // from DOM nodes, so set to undefined instead
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
+ if ( owner.nodeType ) {
+ owner[ this.expando ] = undefined;
+ } else {
+ delete owner[ this.expando ];
+ }
+ }
+ },
+ hasData: function( owner ) {
+ var cache = owner[ this.expando ];
+ return cache !== undefined && !jQuery.isEmptyObject( cache );
}
+};
+var dataPriv = new Data();
- if ( name ) {
+var dataUser = new Data();
- thisCache = pvt ? cache[ id ] : cache[ id ].data;
- if ( thisCache ) {
- // Support array or space separated string names for data keys
- if ( !jQuery.isArray( name ) ) {
+// Implementation Summary
+//
+// 1. Enforce API surface and semantic compatibility with 1.9.x branch
+// 2. Improve the module's maintainability by reducing the storage
+// paths to a single mechanism.
+// 3. Use the same single mechanism to support "private" and "user" data.
+// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
+// 5. Avoid exposing implementation details on user objects (eg. expando properties)
+// 6. Provide a clear path for implementation upgrade to WeakMap in 2014
- // try the string as a key before any manipulation
- if ( name in thisCache ) {
- name = [ name ];
- } else {
+var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+ rmultiDash = /[A-Z]/g;
- // split the camel cased version by spaces unless a key with the spaces exists
- name = jQuery.camelCase( name );
- if ( name in thisCache ) {
- name = [ name ];
- } else {
- name = name.split(" ");
- }
- }
- } else {
- // If "name" is an array of keys...
- // When data is initially created, via ("key", "val") signature,
- // keys will be converted to camelCase.
- // Since there is no way to tell _how_ a key was added, remove
- // both plain key and camelCase key. #12786
- // This will only penalize the array argument path.
- name = name.concat( jQuery.map( name, jQuery.camelCase ) );
- }
+function dataAttr( elem, key, data ) {
+ var name;
- i = name.length;
- while ( i-- ) {
- delete thisCache[ name[i] ];
- }
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+ name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
+ data = elem.getAttribute( name );
- // If there is no data left in the cache, we want to continue
- // and let the cache object itself get destroyed
- if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
- return;
- }
- }
- }
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
- // See jQuery.data for more information
- if ( !pvt ) {
- delete cache[ id ].data;
+ // Only convert to a number if it doesn't change the string
+ +data + "" === data ? +data :
+ rbrace.test( data ) ? JSON.parse( data ) :
+ data;
+ } catch ( e ) {}
- // Don't destroy the parent cache unless the internal data object
- // had been the only thing left in it
- if ( !isEmptyDataObject( cache[ id ] ) ) {
- return;
+ // Make sure we set the data so it isn't changed later
+ dataUser.set( elem, key, data );
+ } else {
+ data = undefined;
}
}
-
- // Destroy the cache
- if ( isNode ) {
- jQuery.cleanData( [ elem ], true );
-
- // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
- /* jshint eqeqeq: false */
- } else if ( support.deleteExpando || cache != cache.window ) {
- /* jshint eqeqeq: true */
- delete cache[ id ];
-
- // When all else fails, null
- } else {
- cache[ id ] = null;
- }
+ return data;
}
-jQuery.extend({
- cache: {},
-
- // The following elements (space-suffixed to avoid Object.prototype collisions)
- // throw uncatchable exceptions if you attempt to set expando properties
- noData: {
- "applet ": true,
- "embed ": true,
- // ...but Flash objects (which have this classid) *can* handle expandos
- "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
- },
-
+jQuery.extend( {
hasData: function( elem ) {
- elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
- return !!elem && !isEmptyDataObject( elem );
+ return dataUser.hasData( elem ) || dataPriv.hasData( elem );
},
data: function( elem, name, data ) {
- return internalData( elem, name, data );
+ return dataUser.access( elem, name, data );
},
removeData: function( elem, name ) {
- return internalRemoveData( elem, name );
+ dataUser.remove( elem, name );
},
- // For internal use only.
+ // TODO: Now that all calls to _data and _removeData have been replaced
+ // with direct calls to dataPriv methods, these can be deprecated.
_data: function( elem, name, data ) {
- return internalData( elem, name, data, true );
+ return dataPriv.access( elem, name, data );
},
_removeData: function( elem, name ) {
- return internalRemoveData( elem, name, true );
+ dataPriv.remove( elem, name );
}
-});
+} );
-jQuery.fn.extend({
+jQuery.fn.extend( {
data: function( key, value ) {
var i, name, data,
- elem = this[0],
+ elem = this[ 0 ],
attrs = elem && elem.attributes;
- // Special expections of .data basically thwart jQuery.access,
- // so implement the relevant behavior ourselves
-
// Gets all values
if ( key === undefined ) {
if ( this.length ) {
- data = jQuery.data( elem );
+ data = dataUser.get( elem );
- if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+ if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
i = attrs.length;
while ( i-- ) {
- // Support: IE11+
+ // Support: IE 11 only
// The attrs elements can be null (#14894)
if ( attrs[ i ] ) {
name = attrs[ i ].name;
if ( name.indexOf( "data-" ) === 0 ) {
- name = jQuery.camelCase( name.slice(5) );
+ name = jQuery.camelCase( name.slice( 5 ) );
dataAttr( elem, name, data[ name ] );
}
}
}
- jQuery._data( elem, "parsedAttrs", true );
+ dataPriv.set( elem, "hasDataAttrs", true );
}
}
@@ -3929,43 +4213,68 @@ jQuery.fn.extend({
// Sets multiple values
if ( typeof key === "object" ) {
- return this.each(function() {
- jQuery.data( this, key );
- });
+ return this.each( function() {
+ dataUser.set( this, key );
+ } );
}
- return arguments.length > 1 ?
+ return access( this, function( value ) {
+ var data;
+
+ // The calling jQuery object (element matches) is not empty
+ // (and therefore has an element appears at this[ 0 ]) and the
+ // `value` parameter was not undefined. An empty jQuery object
+ // will result in `undefined` for elem = this[ 0 ] which will
+ // throw an exception if an attempt to read a data cache is made.
+ if ( elem && value === undefined ) {
+
+ // Attempt to get data from the cache
+ // The key will always be camelCased in Data
+ data = dataUser.get( elem, key );
+ if ( data !== undefined ) {
+ return data;
+ }
+
+ // Attempt to "discover" the data in
+ // HTML5 custom data-* attrs
+ data = dataAttr( elem, key );
+ if ( data !== undefined ) {
+ return data;
+ }
- // Sets one value
- this.each(function() {
- jQuery.data( this, key, value );
- }) :
+ // We tried really hard, but the data doesn't exist.
+ return;
+ }
- // Gets one value
- // Try to fetch any internally stored data first
- elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
+ // Set the data...
+ this.each( function() {
+
+ // We always store the camelCased key
+ dataUser.set( this, key, value );
+ } );
+ }, null, value, arguments.length > 1, null, true );
},
removeData: function( key ) {
- return this.each(function() {
- jQuery.removeData( this, key );
- });
+ return this.each( function() {
+ dataUser.remove( this, key );
+ } );
}
-});
+} );
-jQuery.extend({
+jQuery.extend( {
queue: function( elem, type, data ) {
var queue;
if ( elem ) {
type = ( type || "fx" ) + "queue";
- queue = jQuery._data( elem, type );
+ queue = dataPriv.get( elem, type );
// Speed up dequeue by getting out quickly if this is just a lookup
if ( data ) {
- if ( !queue || jQuery.isArray(data) ) {
- queue = jQuery._data( elem, type, jQuery.makeArray(data) );
+ if ( !queue || jQuery.isArray( data ) ) {
+ queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
} else {
queue.push( data );
}
@@ -3999,7 +4308,7 @@ jQuery.extend({
queue.unshift( "inprogress" );
}
- // clear up the last queue stop function
+ // Clear up the last queue stop function
delete hooks.stop;
fn.call( elem, next, hooks );
}
@@ -4009,19 +4318,18 @@ jQuery.extend({
}
},
- // not intended for public consumption - generates a queueHooks object, or returns the current one
+ // Not public - generate a queueHooks object, or return the current one
_queueHooks: function( elem, type ) {
var key = type + "queueHooks";
- return jQuery._data( elem, key ) || jQuery._data( elem, key, {
- empty: jQuery.Callbacks("once memory").add(function() {
- jQuery._removeData( elem, type + "queue" );
- jQuery._removeData( elem, key );
- })
- });
+ return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
+ empty: jQuery.Callbacks( "once memory" ).add( function() {
+ dataPriv.remove( elem, [ type + "queue", key ] );
+ } )
+ } );
}
-});
+} );
-jQuery.fn.extend({
+jQuery.fn.extend( {
queue: function( type, data ) {
var setter = 2;
@@ -4032,30 +4340,31 @@ jQuery.fn.extend({
}
if ( arguments.length < setter ) {
- return jQuery.queue( this[0], type );
+ return jQuery.queue( this[ 0 ], type );
}
return data === undefined ?
this :
- this.each(function() {
+ this.each( function() {
var queue = jQuery.queue( this, type, data );
- // ensure a hooks for this queue
+ // Ensure a hooks for this queue
jQuery._queueHooks( this, type );
- if ( type === "fx" && queue[0] !== "inprogress" ) {
+ if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
jQuery.dequeue( this, type );
}
- });
+ } );
},
dequeue: function( type ) {
- return this.each(function() {
+ return this.each( function() {
jQuery.dequeue( this, type );
- });
+ } );
},
clearQueue: function( type ) {
return this.queue( type || "fx", [] );
},
+
// Get a promise resolved when queues of a certain type
// are emptied (fx is the type by default)
promise: function( type, obj ) {
@@ -4077,7 +4386,7 @@ jQuery.fn.extend({
type = type || "fx";
while ( i-- ) {
- tmp = jQuery._data( elements[ i ], type + "queueHooks" );
+ tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
if ( tmp && tmp.empty ) {
count++;
tmp.empty.add( resolve );
@@ -4086,171 +4395,400 @@ jQuery.fn.extend({
resolve();
return defer.promise( obj );
}
-});
-var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
+} );
+var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
+
+var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
+
var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
-var isHidden = function( elem, el ) {
- // isHidden might be called from jQuery#filter function;
+var isHiddenWithinTree = function( elem, el ) {
+
+ // isHiddenWithinTree might be called from jQuery#filter function;
// in that case, element will be second argument
elem = el || elem;
- return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+
+ // Inline style trumps all
+ return elem.style.display === "none" ||
+ elem.style.display === "" &&
+
+ // Otherwise, check computed style
+ // Support: Firefox <=43 - 45
+ // Disconnected elements can have computed display: none, so first confirm that elem is
+ // in the document.
+ jQuery.contains( elem.ownerDocument, elem ) &&
+
+ jQuery.css( elem, "display" ) === "none";
};
+var swap = function( elem, options, callback, args ) {
+ var ret, name,
+ old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.apply( elem, args || [] );
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
-// Multifunctional method to get and set values of a collection
-// The value/s can optionally be executed if it's a function
-var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
- var i = 0,
- length = elems.length,
- bulk = key == null;
+ return ret;
+};
- // Sets many values
- if ( jQuery.type( key ) === "object" ) {
- chainable = true;
- for ( i in key ) {
- jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
+
+
+
+function adjustCSS( elem, prop, valueParts, tween ) {
+ var adjusted,
+ scale = 1,
+ maxIterations = 20,
+ currentValue = tween ?
+ function() {
+ return tween.cur();
+ } :
+ function() {
+ return jQuery.css( elem, prop, "" );
+ },
+ initial = currentValue(),
+ unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+ // Starting value computation is required for potential unit mismatches
+ initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
+ rcssNum.exec( jQuery.css( elem, prop ) );
+
+ if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
+
+ // Trust units reported by jQuery.css
+ unit = unit || initialInUnit[ 3 ];
+
+ // Make sure we update the tween properties later on
+ valueParts = valueParts || [];
+
+ // Iteratively approximate from a nonzero starting point
+ initialInUnit = +initial || 1;
+
+ do {
+
+ // If previous iteration zeroed out, double until we get *something*.
+ // Use string for doubling so we don't accidentally see scale as unchanged below
+ scale = scale || ".5";
+
+ // Adjust and apply
+ initialInUnit = initialInUnit / scale;
+ jQuery.style( elem, prop, initialInUnit + unit );
+
+ // Update scale, tolerating zero or NaN from tween.cur()
+ // Break the loop if scale is unchanged or perfect, or if we've just had enough.
+ } while (
+ scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
+ );
+ }
+
+ if ( valueParts ) {
+ initialInUnit = +initialInUnit || +initial || 0;
+
+ // Apply relative offset (+=/-=) if specified
+ adjusted = valueParts[ 1 ] ?
+ initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
+ +valueParts[ 2 ];
+ if ( tween ) {
+ tween.unit = unit;
+ tween.start = initialInUnit;
+ tween.end = adjusted;
}
+ }
+ return adjusted;
+}
- // Sets one value
- } else if ( value !== undefined ) {
- chainable = true;
- if ( !jQuery.isFunction( value ) ) {
- raw = true;
+var defaultDisplayMap = {};
+
+function getDefaultDisplay( elem ) {
+ var temp,
+ doc = elem.ownerDocument,
+ nodeName = elem.nodeName,
+ display = defaultDisplayMap[ nodeName ];
+
+ if ( display ) {
+ return display;
+ }
+
+ temp = doc.body.appendChild( doc.createElement( nodeName ) ),
+ display = jQuery.css( temp, "display" );
+
+ temp.parentNode.removeChild( temp );
+
+ if ( display === "none" ) {
+ display = "block";
+ }
+ defaultDisplayMap[ nodeName ] = display;
+
+ return display;
+}
+
+function showHide( elements, show ) {
+ var display, elem,
+ values = [],
+ index = 0,
+ length = elements.length;
+
+ // Determine new display value for elements that need to change
+ for ( ; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
}
- if ( bulk ) {
- // Bulk operations run against the entire set
- if ( raw ) {
- fn.call( elems, value );
- fn = null;
+ display = elem.style.display;
+ if ( show ) {
- // ...except when executing function values
- } else {
- bulk = fn;
- fn = function( elem, key, value ) {
- return bulk.call( jQuery( elem ), value );
- };
+ // Since we force visibility upon cascade-hidden elements, an immediate (and slow)
+ // check is required in this first loop unless we have a nonempty display value (either
+ // inline or about-to-be-restored)
+ if ( display === "none" ) {
+ values[ index ] = dataPriv.get( elem, "display" ) || null;
+ if ( !values[ index ] ) {
+ elem.style.display = "";
+ }
}
- }
+ if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
+ values[ index ] = getDefaultDisplay( elem );
+ }
+ } else {
+ if ( display !== "none" ) {
+ values[ index ] = "none";
- if ( fn ) {
- for ( ; i < length; i++ ) {
- fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
+ // Remember what we're overwriting
+ dataPriv.set( elem, "display", display );
}
}
}
- return chainable ?
- elems :
+ // Set the display of the elements in a second loop to avoid constant reflow
+ for ( index = 0; index < length; index++ ) {
+ if ( values[ index ] != null ) {
+ elements[ index ].style.display = values[ index ];
+ }
+ }
- // Gets
- bulk ?
- fn.call( elems ) :
- length ? fn( elems[0], key ) : emptyGet;
-};
-var rcheckableType = (/^(?:checkbox|radio)$/i);
+ return elements;
+}
+jQuery.fn.extend( {
+ show: function() {
+ return showHide( this, true );
+ },
+ hide: function() {
+ return showHide( this );
+ },
+ toggle: function( state ) {
+ if ( typeof state === "boolean" ) {
+ return state ? this.show() : this.hide();
+ }
+ return this.each( function() {
+ if ( isHiddenWithinTree( this ) ) {
+ jQuery( this ).show();
+ } else {
+ jQuery( this ).hide();
+ }
+ } );
+ }
+} );
+var rcheckableType = ( /^(?:checkbox|radio)$/i );
-(function() {
- // Minified: var a,b,c
- var input = document.createElement( "input" ),
- div = document.createElement( "div" ),
- fragment = document.createDocumentFragment();
+var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i );
- // Setup
- div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+var rscriptType = ( /^$|\/(?:java|ecma)script/i );
- // IE strips leading whitespace when .innerHTML is used
- support.leadingWhitespace = div.firstChild.nodeType === 3;
- // Make sure that tbody elements aren't automatically inserted
- // IE will insert them into empty tables
- support.tbody = !div.getElementsByTagName( "tbody" ).length;
- // Make sure that link elements get serialized correctly by innerHTML
- // This requires a wrapper element in IE
- support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
+// We have to close these tags to support XHTML (#13200)
+var wrapMap = {
- // Makes sure cloning an html5 element does not cause problems
- // Where outerHTML is undefined, this still works
- support.html5Clone =
- document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";
+ // Support: IE <=9 only
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
- // Check if a disconnected checkbox will retain its checked
- // value of true after appended to the DOM (IE6/7)
- input.type = "checkbox";
- input.checked = true;
- fragment.appendChild( input );
- support.appendChecked = input.checked;
+ // XHTML parsers do not magically insert elements in the
+ // same way that tag soup parsers do. So we cannot shorten
+ // this by omitting <tbody> or other required elements.
+ thead: [ 1, "<table>", "</table>" ],
+ col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
- // Make sure textarea (and checkbox) defaultValue is properly cloned
- // Support: IE6-IE11+
- div.innerHTML = "<textarea>x</textarea>";
- support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+ _default: [ 0, "", "" ]
+};
- // #11217 - WebKit loses check when the name is after the checked attribute
- fragment.appendChild( div );
- div.innerHTML = "<input type='radio' checked='checked' name='t'/>";
+// Support: IE <=9 only
+wrapMap.optgroup = wrapMap.option;
- // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
- // old WebKit doesn't clone checked state correctly in fragments
- support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+
+function getAll( context, tag ) {
+
+ // Support: IE <=9 - 11 only
+ // Use typeof to avoid zero-argument method invocation on host objects (#15151)
+ var ret = typeof context.getElementsByTagName !== "undefined" ?
+ context.getElementsByTagName( tag || "*" ) :
+ typeof context.querySelectorAll !== "undefined" ?
+ context.querySelectorAll( tag || "*" ) :
+ [];
+
+ return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+ jQuery.merge( [ context ], ret ) :
+ ret;
+}
- // Support: IE<9
- // Opera does not clone events (and typeof div.attachEvent === undefined).
- // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
- support.noCloneEvent = true;
- if ( div.attachEvent ) {
- div.attachEvent( "onclick", function() {
- support.noCloneEvent = false;
- });
- div.cloneNode( true ).click();
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+ var i = 0,
+ l = elems.length;
+
+ for ( ; i < l; i++ ) {
+ dataPriv.set(
+ elems[ i ],
+ "globalEval",
+ !refElements || dataPriv.get( refElements[ i ], "globalEval" )
+ );
}
+}
- // Execute the test only if not already executed in another module.
- if (support.deleteExpando == null) {
- // Support: IE<9
- support.deleteExpando = true;
- try {
- delete div.test;
- } catch( e ) {
- support.deleteExpando = false;
+
+var rhtml = /<|&#?\w+;/;
+
+function buildFragment( elems, context, scripts, selection, ignored ) {
+ var elem, tmp, tag, wrap, contains, j,
+ fragment = context.createDocumentFragment(),
+ nodes = [],
+ i = 0,
+ l = elems.length;
+
+ for ( ; i < l; i++ ) {
+ elem = elems[ i ];
+
+ if ( elem || elem === 0 ) {
+
+ // Add nodes directly
+ if ( jQuery.type( elem ) === "object" ) {
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+ // Convert non-html into a text node
+ } else if ( !rhtml.test( elem ) ) {
+ nodes.push( context.createTextNode( elem ) );
+
+ // Convert html into DOM nodes
+ } else {
+ tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
+
+ // Deserialize a standard representation
+ tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
+ wrap = wrapMap[ tag ] || wrapMap._default;
+ tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
+
+ // Descend through wrappers to the right content
+ j = wrap[ 0 ];
+ while ( j-- ) {
+ tmp = tmp.lastChild;
+ }
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( nodes, tmp.childNodes );
+
+ // Remember the top-level container
+ tmp = fragment.firstChild;
+
+ // Ensure the created nodes are orphaned (#12392)
+ tmp.textContent = "";
+ }
}
}
-})();
+ // Remove wrapper from fragment
+ fragment.textContent = "";
-(function() {
- var i, eventName,
- div = document.createElement( "div" );
+ i = 0;
+ while ( ( elem = nodes[ i++ ] ) ) {
- // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
- for ( i in { submit: true, change: true, focusin: true }) {
- eventName = "on" + i;
+ // Skip elements already in the context collection (trac-4087)
+ if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
+ if ( ignored ) {
+ ignored.push( elem );
+ }
+ continue;
+ }
+
+ contains = jQuery.contains( elem.ownerDocument, elem );
- if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
- // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
- div.setAttribute( eventName, "t" );
- support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
+ // Append to fragment
+ tmp = getAll( fragment.appendChild( elem ), "script" );
+
+ // Preserve script evaluation history
+ if ( contains ) {
+ setGlobalEval( tmp );
+ }
+
+ // Capture executables
+ if ( scripts ) {
+ j = 0;
+ while ( ( elem = tmp[ j++ ] ) ) {
+ if ( rscriptType.test( elem.type || "" ) ) {
+ scripts.push( elem );
+ }
+ }
}
}
- // Null elements to avoid leaks in IE.
- div = null;
-})();
+ return fragment;
+}
+
+
+( function() {
+ var fragment = document.createDocumentFragment(),
+ div = fragment.appendChild( document.createElement( "div" ) ),
+ input = document.createElement( "input" );
+
+ // Support: Android 4.0 - 4.3 only
+ // Check state lost if the name is set (#11217)
+ // Support: Windows Web Apps (WWA)
+ // `name` and `type` must use .setAttribute for WWA (#14901)
+ input.setAttribute( "type", "radio" );
+ input.setAttribute( "checked", "checked" );
+ input.setAttribute( "name", "t" );
+
+ div.appendChild( input );
+
+ // Support: Android <=4.1 only
+ // Older WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Support: IE <=11 only
+ // Make sure textarea (and checkbox) defaultValue is properly cloned
+ div.innerHTML = "<textarea>x</textarea>";
+ support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+} )();
+var documentElement = document.documentElement;
+
-var rformElems = /^(?:input|select|textarea)$/i,
+var
rkeyEvent = /^key/,
- rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
- rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
- rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
+ rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
+ rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
function returnTrue() {
return true;
@@ -4260,12 +4798,75 @@ function returnFalse() {
return false;
}
+// Support: IE <=9 only
+// See #13393 for more info
function safeActiveElement() {
try {
return document.activeElement;
} catch ( err ) { }
}
+function on( elem, types, selector, data, fn, one ) {
+ var origFn, type;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) {
+
+ // ( types-Object, data )
+ data = data || selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ on( elem, type, selector, data, types[ type ], one );
+ }
+ return elem;
+ }
+
+ if ( data == null && fn == null ) {
+
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return elem;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return elem.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ } );
+}
+
/*
* Helper functions for managing events -- not part of the public interface.
* Props to Dean Edwards' addEvent library for many of the ideas.
@@ -4275,10 +4876,11 @@ jQuery.event = {
global: {},
add: function( elem, types, handler, data, selector ) {
- var tmp, events, t, handleObjIn,
- special, eventHandle, handleObj,
- handlers, type, namespaces, origType,
- elemData = jQuery._data( elem );
+
+ var handleObjIn, eventHandle, tmp,
+ events, t, handleObj,
+ special, handlers, type, namespaces, origType,
+ elemData = dataPriv.get( elem );
// Don't attach events to noData or text/comment nodes (but allow plain objects)
if ( !elemData ) {
@@ -4292,34 +4894,38 @@ jQuery.event = {
selector = handleObjIn.selector;
}
+ // Ensure that invalid selectors throw exceptions at attach time
+ // Evaluate against documentElement in case elem is a non-element node (e.g., document)
+ if ( selector ) {
+ jQuery.find.matchesSelector( documentElement, selector );
+ }
+
// Make sure that the handler has a unique ID, used to find/remove it later
if ( !handler.guid ) {
handler.guid = jQuery.guid++;
}
// Init the element's event structure and main handler, if this is the first
- if ( !(events = elemData.events) ) {
+ if ( !( events = elemData.events ) ) {
events = elemData.events = {};
}
- if ( !(eventHandle = elemData.handle) ) {
+ if ( !( eventHandle = elemData.handle ) ) {
eventHandle = elemData.handle = function( e ) {
+
// Discard the second event of a jQuery.event.trigger() and
// when an event is called after a page has unloaded
- return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
- jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
- undefined;
+ return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
+ jQuery.event.dispatch.apply( elem, arguments ) : undefined;
};
- // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
- eventHandle.elem = elem;
}
// Handle multiple events separated by a space
types = ( types || "" ).match( rnotwhite ) || [ "" ];
t = types.length;
while ( t-- ) {
- tmp = rtypenamespace.exec( types[t] ) || [];
- type = origType = tmp[1];
- namespaces = ( tmp[2] || "" ).split( "." ).sort();
+ tmp = rtypenamespace.exec( types[ t ] ) || [];
+ type = origType = tmp[ 1 ];
+ namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
// There *must* be a type, no attaching namespace-only handlers
if ( !type ) {
@@ -4336,7 +4942,7 @@ jQuery.event = {
special = jQuery.event.special[ type ] || {};
// handleObj is passed to all event handlers
- handleObj = jQuery.extend({
+ handleObj = jQuery.extend( {
type: type,
origType: origType,
data: data,
@@ -4344,22 +4950,20 @@ jQuery.event = {
guid: handler.guid,
selector: selector,
needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
- namespace: namespaces.join(".")
+ namespace: namespaces.join( "." )
}, handleObjIn );
// Init the event handler queue if we're the first
- if ( !(handlers = events[ type ]) ) {
+ if ( !( handlers = events[ type ] ) ) {
handlers = events[ type ] = [];
handlers.delegateCount = 0;
- // Only use addEventListener/attachEvent if the special events handler returns false
- if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
- // Bind the global event handler to the element
- if ( elem.addEventListener ) {
- elem.addEventListener( type, eventHandle, false );
+ // Only use addEventListener if the special events handler returns false
+ if ( !special.setup ||
+ special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
- } else if ( elem.attachEvent ) {
- elem.attachEvent( "on" + type, eventHandle );
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle );
}
}
}
@@ -4383,19 +4987,17 @@ jQuery.event = {
jQuery.event.global[ type ] = true;
}
- // Nullify elem to prevent memory leaks in IE
- elem = null;
},
// Detach an event or set of events from an element
remove: function( elem, types, handler, selector, mappedTypes ) {
- var j, handleObj, tmp,
- origCount, t, events,
- special, handlers, type,
- namespaces, origType,
- elemData = jQuery.hasData( elem ) && jQuery._data( elem );
- if ( !elemData || !(events = elemData.events) ) {
+ var j, origCount, tmp,
+ events, t, handleObj,
+ special, handlers, type, namespaces, origType,
+ elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
+
+ if ( !elemData || !( events = elemData.events ) ) {
return;
}
@@ -4403,9 +5005,9 @@ jQuery.event = {
types = ( types || "" ).match( rnotwhite ) || [ "" ];
t = types.length;
while ( t-- ) {
- tmp = rtypenamespace.exec( types[t] ) || [];
- type = origType = tmp[1];
- namespaces = ( tmp[2] || "" ).split( "." ).sort();
+ tmp = rtypenamespace.exec( types[ t ] ) || [];
+ type = origType = tmp[ 1 ];
+ namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
// Unbind all events (on this namespace, if provided) for the element
if ( !type ) {
@@ -4418,7 +5020,8 @@ jQuery.event = {
special = jQuery.event.special[ type ] || {};
type = ( selector ? special.delegateType : special.bindType ) || type;
handlers = events[ type ] || [];
- tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
+ tmp = tmp[ 2 ] &&
+ new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
// Remove matching events
origCount = j = handlers.length;
@@ -4428,7 +5031,8 @@ jQuery.event = {
if ( ( mappedTypes || origType === handleObj.origType ) &&
( !handler || handler.guid === handleObj.guid ) &&
( !tmp || tmp.test( handleObj.namespace ) ) &&
- ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+ ( !selector || selector === handleObj.selector ||
+ selector === "**" && handleObj.selector ) ) {
handlers.splice( j, 1 );
if ( handleObj.selector ) {
@@ -4443,7 +5047,9 @@ jQuery.event = {
// Remove generic event handler if we removed something and no more handlers exist
// (avoids potential for endless recursion during removal of special event handlers)
if ( origCount && !handlers.length ) {
- if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+ if ( !special.teardown ||
+ special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+
jQuery.removeEvent( elem, type, elemData.handle );
}
@@ -4451,167 +5057,29 @@ jQuery.event = {
}
}
- // Remove the expando if it's no longer used
+ // Remove data and the expando if it's no longer used
if ( jQuery.isEmptyObject( events ) ) {
- delete elemData.handle;
-
- // removeData also checks for emptiness and clears the expando if empty
- // so use it instead of delete
- jQuery._removeData( elem, "events" );
+ dataPriv.remove( elem, "handle events" );
}
},
- trigger: function( event, data, elem, onlyHandlers ) {
- var handle, ontype, cur,
- bubbleType, special, tmp, i,
- eventPath = [ elem || document ],
- type = hasOwn.call( event, "type" ) ? event.type : event,
- namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
-
- cur = tmp = elem = elem || document;
-
- // Don't do events on text and comment nodes
- if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
- return;
- }
-
- // focus/blur morphs to focusin/out; ensure we're not firing them right now
- if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
- return;
- }
-
- if ( type.indexOf(".") >= 0 ) {
- // Namespaced trigger; create a regexp to match event type in handle()
- namespaces = type.split(".");
- type = namespaces.shift();
- namespaces.sort();
- }
- ontype = type.indexOf(":") < 0 && "on" + type;
-
- // Caller can pass in a jQuery.Event object, Object, or just an event type string
- event = event[ jQuery.expando ] ?
- event :
- new jQuery.Event( type, typeof event === "object" && event );
-
- // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
- event.isTrigger = onlyHandlers ? 2 : 3;
- event.namespace = namespaces.join(".");
- event.namespace_re = event.namespace ?
- new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
- null;
-
- // Clean up the event in case it is being reused
- event.result = undefined;
- if ( !event.target ) {
- event.target = elem;
- }
-
- // Clone any incoming data and prepend the event, creating the handler arg list
- data = data == null ?
- [ event ] :
- jQuery.makeArray( data, [ event ] );
-
- // Allow special events to draw outside the lines
- special = jQuery.event.special[ type ] || {};
- if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
- return;
- }
-
- // Determine event propagation path in advance, per W3C events spec (#9951)
- // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
- if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
-
- bubbleType = special.delegateType || type;
- if ( !rfocusMorph.test( bubbleType + type ) ) {
- cur = cur.parentNode;
- }
- for ( ; cur; cur = cur.parentNode ) {
- eventPath.push( cur );
- tmp = cur;
- }
-
- // Only add window if we got to document (e.g., not plain obj or detached DOM)
- if ( tmp === (elem.ownerDocument || document) ) {
- eventPath.push( tmp.defaultView || tmp.parentWindow || window );
- }
- }
-
- // Fire handlers on the event path
- i = 0;
- while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
-
- event.type = i > 1 ?
- bubbleType :
- special.bindType || type;
-
- // jQuery handler
- handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
- if ( handle ) {
- handle.apply( cur, data );
- }
-
- // Native handler
- handle = ontype && cur[ ontype ];
- if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
- event.result = handle.apply( cur, data );
- if ( event.result === false ) {
- event.preventDefault();
- }
- }
- }
- event.type = type;
-
- // If nobody prevented the default action, do it now
- if ( !onlyHandlers && !event.isDefaultPrevented() ) {
-
- if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
- jQuery.acceptData( elem ) ) {
-
- // Call a native DOM method on the target with the same name name as the event.
- // Can't use an .isFunction() check here because IE6/7 fails that test.
- // Don't do default actions on window, that's where global variables be (#6170)
- if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
-
- // Don't re-trigger an onFOO event when we call its FOO() method
- tmp = elem[ ontype ];
-
- if ( tmp ) {
- elem[ ontype ] = null;
- }
-
- // Prevent re-triggering of the same event, since we already bubbled it above
- jQuery.event.triggered = type;
- try {
- elem[ type ]();
- } catch ( e ) {
- // IE<9 dies on focus/blur to hidden element (#1486,#12518)
- // only reproducible on winXP IE8 native, not IE9 in IE8 mode
- }
- jQuery.event.triggered = undefined;
-
- if ( tmp ) {
- elem[ ontype ] = tmp;
- }
- }
- }
- }
-
- return event.result;
- },
-
- dispatch: function( event ) {
+ dispatch: function( nativeEvent ) {
// Make a writable jQuery.Event from the native event object
- event = jQuery.event.fix( event );
+ var event = jQuery.event.fix( nativeEvent );
- var i, ret, handleObj, matched, j,
- handlerQueue = [],
- args = slice.call( arguments ),
- handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
+ var i, j, ret, matched, handleObj, handlerQueue,
+ args = new Array( arguments.length ),
+ handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
special = jQuery.event.special[ event.type ] || {};
// Use the fix-ed jQuery.Event rather than the (read-only) native event
- args[0] = event;
+ args[ 0 ] = event;
+
+ for ( i = 1; i < arguments.length; i++ ) {
+ args[ i ] = arguments[ i ];
+ }
+
event.delegateTarget = this;
// Call the preDispatch hook for the mapped type, and let it bail if desired
@@ -4624,24 +5092,25 @@ jQuery.event = {
// Run delegates first; they may want to stop propagation beneath us
i = 0;
- while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
+ while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
event.currentTarget = matched.elem;
j = 0;
- while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
+ while ( ( handleObj = matched.handlers[ j++ ] ) &&
+ !event.isImmediatePropagationStopped() ) {
- // Triggered event must either 1) have no namespace, or
- // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
- if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
+ // Triggered event must either 1) have no namespace, or 2) have namespace(s)
+ // a subset or equal to those in the bound event (both can have no namespace).
+ if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
event.handleObj = handleObj;
event.data = handleObj.data;
- ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
- .apply( matched.elem, args );
+ ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
+ handleObj.handler ).apply( matched.elem, args );
if ( ret !== undefined ) {
- if ( (event.result = ret) === false ) {
+ if ( ( event.result = ret ) === false ) {
event.preventDefault();
event.stopPropagation();
}
@@ -4659,23 +5128,25 @@ jQuery.event = {
},
handlers: function( event, handlers ) {
- var sel, handleObj, matches, i,
+ var i, matches, sel, handleObj,
handlerQueue = [],
delegateCount = handlers.delegateCount,
cur = event.target;
+ // Support: IE <=9
// Find delegate handlers
// Black-hole SVG <use> instance trees (#13180)
- // Avoid non-left-click bubbling in Firefox (#3861)
- if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
+ //
+ // Support: Firefox <=42
+ // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343)
+ if ( delegateCount && cur.nodeType &&
+ ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) {
- /* jshint eqeqeq: false */
- for ( ; cur != this; cur = cur.parentNode || this ) {
- /* jshint eqeqeq: true */
+ for ( ; cur !== this; cur = cur.parentNode || this ) {
// Don't check non-elements (#13208)
// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
- if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
+ if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) {
matches = [];
for ( i = 0; i < delegateCount; i++ ) {
handleObj = handlers[ i ];
@@ -4685,7 +5156,7 @@ jQuery.event = {
if ( matches[ sel ] === undefined ) {
matches[ sel ] = handleObj.needsContext ?
- jQuery( sel, this ).index( cur ) >= 0 :
+ jQuery( sel, this ).index( cur ) > -1 :
jQuery.find( sel, this, null, [ cur ] ).length;
}
if ( matches[ sel ] ) {
@@ -4693,7 +5164,7 @@ jQuery.event = {
}
}
if ( matches.length ) {
- handlerQueue.push({ elem: cur, handlers: matches });
+ handlerQueue.push( { elem: cur, handlers: matches } );
}
}
}
@@ -4701,125 +5172,59 @@ jQuery.event = {
// Add the remaining (directly-bound) handlers
if ( delegateCount < handlers.length ) {
- handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
+ handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } );
}
return handlerQueue;
},
- fix: function( event ) {
- if ( event[ jQuery.expando ] ) {
- return event;
- }
-
- // Create a writable copy of the event object and normalize some properties
- var i, prop, copy,
- type = event.type,
- originalEvent = event,
- fixHook = this.fixHooks[ type ];
-
- if ( !fixHook ) {
- this.fixHooks[ type ] = fixHook =
- rmouseEvent.test( type ) ? this.mouseHooks :
- rkeyEvent.test( type ) ? this.keyHooks :
- {};
- }
- copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
-
- event = new jQuery.Event( originalEvent );
-
- i = copy.length;
- while ( i-- ) {
- prop = copy[ i ];
- event[ prop ] = originalEvent[ prop ];
- }
-
- // Support: IE<9
- // Fix target property (#1925)
- if ( !event.target ) {
- event.target = originalEvent.srcElement || document;
- }
-
- // Support: Chrome 23+, Safari?
- // Target should not be a text node (#504, #13143)
- if ( event.target.nodeType === 3 ) {
- event.target = event.target.parentNode;
- }
-
- // Support: IE<9
- // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
- event.metaKey = !!event.metaKey;
-
- return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
- },
-
- // Includes some event props shared by KeyEvent and MouseEvent
- props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+ addProp: function( name, hook ) {
+ Object.defineProperty( jQuery.Event.prototype, name, {
+ enumerable: true,
+ configurable: true,
- fixHooks: {},
-
- keyHooks: {
- props: "char charCode key keyCode".split(" "),
- filter: function( event, original ) {
+ get: jQuery.isFunction( hook ) ?
+ function() {
+ if ( this.originalEvent ) {
+ return hook( this.originalEvent );
+ }
+ } :
+ function() {
+ if ( this.originalEvent ) {
+ return this.originalEvent[ name ];
+ }
+ },
- // Add which for key events
- if ( event.which == null ) {
- event.which = original.charCode != null ? original.charCode : original.keyCode;
+ set: function( value ) {
+ Object.defineProperty( this, name, {
+ enumerable: true,
+ configurable: true,
+ writable: true,
+ value: value
+ } );
}
-
- return event;
- }
+ } );
},
- mouseHooks: {
- props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
- filter: function( event, original ) {
- var body, eventDoc, doc,
- button = original.button,
- fromElement = original.fromElement;
-
- // Calculate pageX/Y if missing and clientX/Y available
- if ( event.pageX == null && original.clientX != null ) {
- eventDoc = event.target.ownerDocument || document;
- doc = eventDoc.documentElement;
- body = eventDoc.body;
-
- event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
- event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
- }
-
- // Add relatedTarget, if necessary
- if ( !event.relatedTarget && fromElement ) {
- event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
- }
-
- // Add which for click: 1 === left; 2 === middle; 3 === right
- // Note: button is not normalized, so don't use it
- if ( !event.which && button !== undefined ) {
- event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
- }
-
- return event;
- }
+ fix: function( originalEvent ) {
+ return originalEvent[ jQuery.expando ] ?
+ originalEvent :
+ new jQuery.Event( originalEvent );
},
special: {
load: {
+
// Prevent triggered image.load events from bubbling to window.load
noBubble: true
},
focus: {
+
// Fire native event if possible so blur/focus sequence is correct
trigger: function() {
if ( this !== safeActiveElement() && this.focus ) {
- try {
- this.focus();
- return false;
- } catch ( e ) {
- // Support: IE<9
- // If we error on focus to hidden element (#1486, #12518),
- // let .trigger() run the handlers
- }
+ this.focus();
+ return false;
}
},
delegateType: "focusin"
@@ -4834,9 +5239,10 @@ jQuery.event = {
delegateType: "focusout"
},
click: {
+
// For checkbox, fire native event so checked state will be right
trigger: function() {
- if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
+ if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
this.click();
return false;
}
@@ -4858,56 +5264,21 @@ jQuery.event = {
}
}
}
- },
-
- simulate: function( type, elem, event, bubble ) {
- // Piggyback on a donor event to simulate a different one.
- // Fake originalEvent to avoid donor's stopPropagation, but if the
- // simulated event prevents default then we do the same on the donor.
- var e = jQuery.extend(
- new jQuery.Event(),
- event,
- {
- type: type,
- isSimulated: true,
- originalEvent: {}
- }
- );
- if ( bubble ) {
- jQuery.event.trigger( e, null, elem );
- } else {
- jQuery.event.dispatch.call( elem, e );
- }
- if ( e.isDefaultPrevented() ) {
- event.preventDefault();
- }
}
};
-jQuery.removeEvent = document.removeEventListener ?
- function( elem, type, handle ) {
- if ( elem.removeEventListener ) {
- elem.removeEventListener( type, handle, false );
- }
- } :
- function( elem, type, handle ) {
- var name = "on" + type;
+jQuery.removeEvent = function( elem, type, handle ) {
- if ( elem.detachEvent ) {
-
- // #8545, #7054, preventing memory leaks for custom events in IE6-8
- // detachEvent needed property on element, by name of that event, to properly expose it to GC
- if ( typeof elem[ name ] === strundefined ) {
- elem[ name ] = null;
- }
-
- elem.detachEvent( name, handle );
- }
- };
+ // This "if" is needed for plain objects
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle );
+ }
+};
jQuery.Event = function( src, props ) {
+
// Allow instantiation without the 'new' keyword
- if ( !(this instanceof jQuery.Event) ) {
+ if ( !( this instanceof jQuery.Event ) ) {
return new jQuery.Event( src, props );
}
@@ -4920,11 +5291,22 @@ jQuery.Event = function( src, props ) {
// by a handler lower down the tree; reflect the correct value.
this.isDefaultPrevented = src.defaultPrevented ||
src.defaultPrevented === undefined &&
- // Support: IE < 9, Android < 4.0
+
+ // Support: Android <=2.3 only
src.returnValue === false ?
returnTrue :
returnFalse;
+ // Create target properties
+ // Support: Safari <=6 - 7 only
+ // Target should not be a text node (#504, #13143)
+ this.target = ( src.target && src.target.nodeType === 3 ) ?
+ src.target.parentNode :
+ src.target;
+
+ this.currentTarget = src.currentTarget;
+ this.relatedTarget = src.relatedTarget;
+
// Event type
} else {
this.type = src;
@@ -4943,52 +5325,38 @@ jQuery.Event = function( src, props ) {
};
// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
-// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
jQuery.Event.prototype = {
+ constructor: jQuery.Event,
isDefaultPrevented: returnFalse,
isPropagationStopped: returnFalse,
isImmediatePropagationStopped: returnFalse,
+ isSimulated: false,
preventDefault: function() {
var e = this.originalEvent;
this.isDefaultPrevented = returnTrue;
- if ( !e ) {
- return;
- }
- // If preventDefault exists, run it on the original event
- if ( e.preventDefault ) {
+ if ( e && !this.isSimulated ) {
e.preventDefault();
-
- // Support: IE
- // Otherwise set the returnValue property of the original event to false
- } else {
- e.returnValue = false;
}
},
stopPropagation: function() {
var e = this.originalEvent;
this.isPropagationStopped = returnTrue;
- if ( !e ) {
- return;
- }
- // If stopPropagation exists, run it on the original event
- if ( e.stopPropagation ) {
+
+ if ( e && !this.isSimulated ) {
e.stopPropagation();
}
-
- // Support: IE
- // Set the cancelBubble property of the original event to true
- e.cancelBubble = true;
},
stopImmediatePropagation: function() {
var e = this.originalEvent;
this.isImmediatePropagationStopped = returnTrue;
- if ( e && e.stopImmediatePropagation ) {
+ if ( e && !this.isSimulated ) {
e.stopImmediatePropagation();
}
@@ -4996,8 +5364,64 @@ jQuery.Event.prototype = {
}
};
+// Includes all common event props including KeyEvent and MouseEvent specific props
+jQuery.each( {
+ altKey: true,
+ bubbles: true,
+ cancelable: true,
+ changedTouches: true,
+ ctrlKey: true,
+ detail: true,
+ eventPhase: true,
+ metaKey: true,
+ pageX: true,
+ pageY: true,
+ shiftKey: true,
+ view: true,
+ "char": true,
+ charCode: true,
+ key: true,
+ keyCode: true,
+ button: true,
+ buttons: true,
+ clientX: true,
+ clientY: true,
+ offsetX: true,
+ offsetY: true,
+ pointerId: true,
+ pointerType: true,
+ screenX: true,
+ screenY: true,
+ targetTouches: true,
+ toElement: true,
+ touches: true,
+
+ which: function( event ) {
+ var button = event.button;
+
+ // Add which for key events
+ if ( event.which == null && rkeyEvent.test( event.type ) ) {
+ return event.charCode != null ? event.charCode : event.keyCode;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
+ return ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event.which;
+ }
+}, jQuery.event.addProp );
+
// Create mouseenter/leave events using mouseover/out and event-time checks
-jQuery.each({
+// so that event delegation works in jQuery.
+// Do the same for pointerenter/pointerleave and pointerover/pointerout
+//
+// Support: Safari 7 only
+// Safari sends mouseenter too often; see:
+// https://bugs.chromium.org/p/chromium/issues/detail?id=470258
+// for the description of the bug (it existed in older Chrome versions as well).
+jQuery.each( {
mouseenter: "mouseover",
mouseleave: "mouseout",
pointerenter: "pointerover",
@@ -5013,9 +5437,9 @@ jQuery.each({
related = event.relatedTarget,
handleObj = event.handleObj;
- // For mousenter/leave call the handler if related is outside the target.
+ // For mouseenter/leave call the handler if related is outside the target.
// NB: No relatedTarget if the mouse left/entered the browser window
- if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+ if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
event.type = handleObj.origType;
ret = handleObj.handler.apply( this, arguments );
event.type = fix;
@@ -5023,219 +5447,33 @@ jQuery.each({
return ret;
}
};
-});
-
-// IE submit delegation
-if ( !support.submitBubbles ) {
+} );
- jQuery.event.special.submit = {
- setup: function() {
- // Only need this for delegated form submit events
- if ( jQuery.nodeName( this, "form" ) ) {
- return false;
- }
+jQuery.fn.extend( {
- // Lazy-add a submit handler when a descendant form may potentially be submitted
- jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
- // Node name check avoids a VML-related crash in IE (#9807)
- var elem = e.target,
- form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
- if ( form && !jQuery._data( form, "submitBubbles" ) ) {
- jQuery.event.add( form, "submit._submit", function( event ) {
- event._submit_bubble = true;
- });
- jQuery._data( form, "submitBubbles", true );
- }
- });
- // return undefined since we don't need an event listener
- },
-
- postDispatch: function( event ) {
- // If form was submitted by the user, bubble the event up the tree
- if ( event._submit_bubble ) {
- delete event._submit_bubble;
- if ( this.parentNode && !event.isTrigger ) {
- jQuery.event.simulate( "submit", this.parentNode, event, true );
- }
- }
- },
-
- teardown: function() {
- // Only need this for delegated form submit events
- if ( jQuery.nodeName( this, "form" ) ) {
- return false;
- }
-
- // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
- jQuery.event.remove( this, "._submit" );
- }
- };
-}
-
-// IE change delegation and checkbox/radio fix
-if ( !support.changeBubbles ) {
-
- jQuery.event.special.change = {
-
- setup: function() {
-
- if ( rformElems.test( this.nodeName ) ) {
- // IE doesn't fire change on a check/radio until blur; trigger it on click
- // after a propertychange. Eat the blur-change in special.change.handle.
- // This still fires onchange a second time for check/radio after blur.
- if ( this.type === "checkbox" || this.type === "radio" ) {
- jQuery.event.add( this, "propertychange._change", function( event ) {
- if ( event.originalEvent.propertyName === "checked" ) {
- this._just_changed = true;
- }
- });
- jQuery.event.add( this, "click._change", function( event ) {
- if ( this._just_changed && !event.isTrigger ) {
- this._just_changed = false;
- }
- // Allow triggered, simulated change events (#11500)
- jQuery.event.simulate( "change", this, event, true );
- });
- }
- return false;
- }
- // Delegated event; lazy-add a change handler on descendant inputs
- jQuery.event.add( this, "beforeactivate._change", function( e ) {
- var elem = e.target;
-
- if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
- jQuery.event.add( elem, "change._change", function( event ) {
- if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
- jQuery.event.simulate( "change", this.parentNode, event, true );
- }
- });
- jQuery._data( elem, "changeBubbles", true );
- }
- });
- },
-
- handle: function( event ) {
- var elem = event.target;
-
- // Swallow native change events from checkbox/radio, we already triggered them above
- if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
- return event.handleObj.handler.apply( this, arguments );
- }
- },
-
- teardown: function() {
- jQuery.event.remove( this, "._change" );
-
- return !rformElems.test( this.nodeName );
- }
- };
-}
-
-// Create "bubbling" focus and blur events
-if ( !support.focusinBubbles ) {
- jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
-
- // Attach a single capturing handler on the document while someone wants focusin/focusout
- var handler = function( event ) {
- jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
- };
-
- jQuery.event.special[ fix ] = {
- setup: function() {
- var doc = this.ownerDocument || this,
- attaches = jQuery._data( doc, fix );
-
- if ( !attaches ) {
- doc.addEventListener( orig, handler, true );
- }
- jQuery._data( doc, fix, ( attaches || 0 ) + 1 );
- },
- teardown: function() {
- var doc = this.ownerDocument || this,
- attaches = jQuery._data( doc, fix ) - 1;
-
- if ( !attaches ) {
- doc.removeEventListener( orig, handler, true );
- jQuery._removeData( doc, fix );
- } else {
- jQuery._data( doc, fix, attaches );
- }
- }
- };
- });
-}
-
-jQuery.fn.extend({
-
- on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
- var type, origFn;
-
- // Types can be a map of types/handlers
- if ( typeof types === "object" ) {
- // ( types-Object, selector, data )
- if ( typeof selector !== "string" ) {
- // ( types-Object, data )
- data = data || selector;
- selector = undefined;
- }
- for ( type in types ) {
- this.on( type, selector, data, types[ type ], one );
- }
- return this;
- }
-
- if ( data == null && fn == null ) {
- // ( types, fn )
- fn = selector;
- data = selector = undefined;
- } else if ( fn == null ) {
- if ( typeof selector === "string" ) {
- // ( types, selector, fn )
- fn = data;
- data = undefined;
- } else {
- // ( types, data, fn )
- fn = data;
- data = selector;
- selector = undefined;
- }
- }
- if ( fn === false ) {
- fn = returnFalse;
- } else if ( !fn ) {
- return this;
- }
-
- if ( one === 1 ) {
- origFn = fn;
- fn = function( event ) {
- // Can use an empty set, since event contains the info
- jQuery().off( event );
- return origFn.apply( this, arguments );
- };
- // Use same guid so caller can remove using origFn
- fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
- }
- return this.each( function() {
- jQuery.event.add( this, types, fn, data, selector );
- });
+ on: function( types, selector, data, fn ) {
+ return on( this, types, selector, data, fn );
},
one: function( types, selector, data, fn ) {
- return this.on( types, selector, data, fn, 1 );
+ return on( this, types, selector, data, fn, 1 );
},
off: function( types, selector, fn ) {
var handleObj, type;
if ( types && types.preventDefault && types.handleObj ) {
+
// ( event ) dispatched jQuery.Event
handleObj = types.handleObj;
jQuery( types.delegateTarget ).off(
- handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+ handleObj.namespace ?
+ handleObj.origType + "." + handleObj.namespace :
+ handleObj.origType,
handleObj.selector,
handleObj.handler
);
return this;
}
if ( typeof types === "object" ) {
+
// ( types-object [, selector] )
for ( type in types ) {
this.off( type, selector, types[ type ] );
@@ -5243,6 +5481,7 @@ jQuery.fn.extend({
return this;
}
if ( selector === false || typeof selector === "function" ) {
+
// ( types [, fn] )
fn = selector;
selector = undefined;
@@ -5250,263 +5489,238 @@ jQuery.fn.extend({
if ( fn === false ) {
fn = returnFalse;
}
- return this.each(function() {
+ return this.each( function() {
jQuery.event.remove( this, types, fn, selector );
- });
- },
-
- trigger: function( type, data ) {
- return this.each(function() {
- jQuery.event.trigger( type, data, this );
- });
- },
- triggerHandler: function( type, data ) {
- var elem = this[0];
- if ( elem ) {
- return jQuery.event.trigger( type, data, elem, true );
- }
+ } );
}
-});
+} );
-function createSafeFragment( document ) {
- var list = nodeNames.split( "|" ),
- safeFrag = document.createDocumentFragment();
+var
- if ( safeFrag.createElement ) {
- while ( list.length ) {
- safeFrag.createElement(
- list.pop()
- );
- }
- }
- return safeFrag;
-}
+ /* eslint-disable max-len */
-var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
- "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
- rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
- rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
- rleadingWhitespace = /^\s+/,
- rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
- rtagName = /<([\w:]+)/,
- rtbody = /<tbody/i,
- rhtml = /<|&#?\w+;/,
- rnoInnerhtml = /<(?:script|style|link)/i,
- // checked="checked" or checked
- rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
- rscriptType = /^$|\/(?:java|ecma)script/i,
- rscriptTypeMasked = /^true\/(.*)/,
- rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
-
- // We have to close these tags to support XHTML (#13200)
- wrapMap = {
- option: [ 1, "<select multiple='multiple'>", "</select>" ],
- legend: [ 1, "<fieldset>", "</fieldset>" ],
- area: [ 1, "<map>", "</map>" ],
- param: [ 1, "<object>", "</object>" ],
- thead: [ 1, "<table>", "</table>" ],
- tr: [ 2, "<table><tbody>", "</tbody></table>" ],
- col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
- td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
-
- // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
- // unless wrapped in a div with non-breaking characters in front of it.
- _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
- },
- safeFragment = createSafeFragment( document ),
- fragmentDiv = safeFragment.appendChild( document.createElement("div") );
+ // See https://github.com/eslint/eslint/issues/3229
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
-wrapMap.optgroup = wrapMap.option;
-wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
-wrapMap.th = wrapMap.td;
+ /* eslint-enable */
-function getAll( context, tag ) {
- var elems, elem,
- i = 0,
- found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) :
- typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) :
- undefined;
+ // Support: IE <=10 - 11, Edge 12 - 13
+ // In IE/Edge using regex groups here causes severe slowdowns.
+ // See https://connect.microsoft.com/IE/feedback/details/1736512/
+ rnoInnerhtml = /<script|<style|<link/i,
- if ( !found ) {
- for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
- if ( !tag || jQuery.nodeName( elem, tag ) ) {
- found.push( elem );
- } else {
- jQuery.merge( found, getAll( elem, tag ) );
- }
- }
- }
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptTypeMasked = /^true\/(.*)/,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
- return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
- jQuery.merge( [ context ], found ) :
- found;
-}
+function manipulationTarget( elem, content ) {
+ if ( jQuery.nodeName( elem, "table" ) &&
+ jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
-// Used in buildFragment, fixes the defaultChecked property
-function fixDefaultChecked( elem ) {
- if ( rcheckableType.test( elem.type ) ) {
- elem.defaultChecked = elem.checked;
+ return elem.getElementsByTagName( "tbody" )[ 0 ] || elem;
}
-}
-// Support: IE<8
-// Manipulating tables requires a tbody
-function manipulationTarget( elem, content ) {
- return jQuery.nodeName( elem, "table" ) &&
- jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
-
- elem.getElementsByTagName("tbody")[0] ||
- elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
- elem;
+ return elem;
}
// Replace/restore the type attribute of script elements for safe DOM manipulation
function disableScript( elem ) {
- elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type;
+ elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
return elem;
}
function restoreScript( elem ) {
var match = rscriptTypeMasked.exec( elem.type );
+
if ( match ) {
- elem.type = match[1];
+ elem.type = match[ 1 ];
} else {
- elem.removeAttribute("type");
+ elem.removeAttribute( "type" );
}
- return elem;
-}
-// Mark scripts as having already been evaluated
-function setGlobalEval( elems, refElements ) {
- var elem,
- i = 0;
- for ( ; (elem = elems[i]) != null; i++ ) {
- jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
- }
+ return elem;
}
function cloneCopyEvent( src, dest ) {
+ var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
- if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+ if ( dest.nodeType !== 1 ) {
return;
}
- var type, i, l,
- oldData = jQuery._data( src ),
- curData = jQuery._data( dest, oldData ),
- events = oldData.events;
+ // 1. Copy private data: events, handlers, etc.
+ if ( dataPriv.hasData( src ) ) {
+ pdataOld = dataPriv.access( src );
+ pdataCur = dataPriv.set( dest, pdataOld );
+ events = pdataOld.events;
- if ( events ) {
- delete curData.handle;
- curData.events = {};
+ if ( events ) {
+ delete pdataCur.handle;
+ pdataCur.events = {};
- for ( type in events ) {
- for ( i = 0, l = events[ type ].length; i < l; i++ ) {
- jQuery.event.add( dest, type, events[ type ][ i ] );
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type, events[ type ][ i ] );
+ }
}
}
}
- // make the cloned public data object a copy from the original
- if ( curData.data ) {
- curData.data = jQuery.extend( {}, curData.data );
+ // 2. Copy user data
+ if ( dataUser.hasData( src ) ) {
+ udataOld = dataUser.access( src );
+ udataCur = jQuery.extend( {}, udataOld );
+
+ dataUser.set( dest, udataCur );
}
}
-function fixCloneNodeIssues( src, dest ) {
- var nodeName, e, data;
+// Fix IE bugs, see support tests
+function fixInput( src, dest ) {
+ var nodeName = dest.nodeName.toLowerCase();
- // We do not need to do anything for non-Elements
- if ( dest.nodeType !== 1 ) {
- return;
+ // Fails to persist the checked state of a cloned checkbox or radio button.
+ if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+ dest.checked = src.checked;
+
+ // Fails to return the selected option to the default selected state when cloning options
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
}
+}
- nodeName = dest.nodeName.toLowerCase();
+function domManip( collection, args, callback, ignored ) {
- // IE6-8 copies events bound via attachEvent when using cloneNode.
- if ( !support.noCloneEvent && dest[ jQuery.expando ] ) {
- data = jQuery._data( dest );
+ // Flatten any nested arrays
+ args = concat.apply( [], args );
- for ( e in data.events ) {
- jQuery.removeEvent( dest, e, data.handle );
- }
+ var fragment, first, scripts, hasScripts, node, doc,
+ i = 0,
+ l = collection.length,
+ iNoClone = l - 1,
+ value = args[ 0 ],
+ isFunction = jQuery.isFunction( value );
- // Event data gets referenced instead of copied if the expando gets copied too
- dest.removeAttribute( jQuery.expando );
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( isFunction ||
+ ( l > 1 && typeof value === "string" &&
+ !support.checkClone && rchecked.test( value ) ) ) {
+ return collection.each( function( index ) {
+ var self = collection.eq( index );
+ if ( isFunction ) {
+ args[ 0 ] = value.call( this, index, self.html() );
+ }
+ domManip( self, args, callback, ignored );
+ } );
}
- // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
- if ( nodeName === "script" && dest.text !== src.text ) {
- disableScript( dest ).text = src.text;
- restoreScript( dest );
+ if ( l ) {
+ fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
+ first = fragment.firstChild;
- // IE6-10 improperly clones children of object elements using classid.
- // IE10 throws NoModificationAllowedError if parent is null, #12132.
- } else if ( nodeName === "object" ) {
- if ( dest.parentNode ) {
- dest.outerHTML = src.outerHTML;
+ if ( fragment.childNodes.length === 1 ) {
+ fragment = first;
}
- // This path appears unavoidable for IE9. When cloning an object
- // element in IE9, the outerHTML strategy above is not sufficient.
- // If the src has innerHTML and the destination does not,
- // copy the src.innerHTML into the dest.innerHTML. #10324
- if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
- dest.innerHTML = src.innerHTML;
- }
+ // Require either new content or an interest in ignored elements to invoke the callback
+ if ( first || ignored ) {
+ scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+ hasScripts = scripts.length;
- } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
- // IE6-8 fails to persist the checked state of a cloned checkbox
- // or radio button. Worse, IE6-7 fail to give the cloned element
- // a checked appearance if the defaultChecked value isn't also set
+ // Use the original fragment for the last item
+ // instead of the first because it can end up
+ // being emptied incorrectly in certain situations (#8070).
+ for ( ; i < l; i++ ) {
+ node = fragment;
- dest.defaultChecked = dest.checked = src.checked;
+ if ( i !== iNoClone ) {
+ node = jQuery.clone( node, true, true );
- // IE6-7 get confused and end up setting the value of a cloned
- // checkbox/radio button to an empty string instead of "on"
- if ( dest.value !== src.value ) {
- dest.value = src.value;
- }
+ // Keep references to cloned scripts for later restoration
+ if ( hasScripts ) {
- // IE6-8 fails to return the selected option to the default selected
- // state when cloning options
- } else if ( nodeName === "option" ) {
- dest.defaultSelected = dest.selected = src.defaultSelected;
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( scripts, getAll( node, "script" ) );
+ }
+ }
- // IE6-8 fails to set the defaultValue to the correct value when
- // cloning other types of input fields
- } else if ( nodeName === "input" || nodeName === "textarea" ) {
- dest.defaultValue = src.defaultValue;
+ callback.call( collection[ i ], node, i );
+ }
+
+ if ( hasScripts ) {
+ doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+ // Reenable scripts
+ jQuery.map( scripts, restoreScript );
+
+ // Evaluate executable scripts on first document insertion
+ for ( i = 0; i < hasScripts; i++ ) {
+ node = scripts[ i ];
+ if ( rscriptType.test( node.type || "" ) &&
+ !dataPriv.access( node, "globalEval" ) &&
+ jQuery.contains( doc, node ) ) {
+
+ if ( node.src ) {
+
+ // Optional AJAX dependency, but won't run scripts if not present
+ if ( jQuery._evalUrl ) {
+ jQuery._evalUrl( node.src );
+ }
+ } else {
+ DOMEval( node.textContent.replace( rcleanScript, "" ), doc );
+ }
+ }
+ }
+ }
+ }
}
+
+ return collection;
}
-jQuery.extend({
- clone: function( elem, dataAndEvents, deepDataAndEvents ) {
- var destElements, node, clone, i, srcElements,
- inPage = jQuery.contains( elem.ownerDocument, elem );
+function remove( elem, selector, keepData ) {
+ var node,
+ nodes = selector ? jQuery.filter( selector, elem ) : elem,
+ i = 0;
- if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
- clone = elem.cloneNode( true );
+ for ( ; ( node = nodes[ i ] ) != null; i++ ) {
+ if ( !keepData && node.nodeType === 1 ) {
+ jQuery.cleanData( getAll( node ) );
+ }
- // IE<=8 does not properly clone detached, unknown element nodes
- } else {
- fragmentDiv.innerHTML = elem.outerHTML;
- fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
+ if ( node.parentNode ) {
+ if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
+ setGlobalEval( getAll( node, "script" ) );
+ }
+ node.parentNode.removeChild( node );
}
+ }
+
+ return elem;
+}
- if ( (!support.noCloneEvent || !support.noCloneChecked) &&
- (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+jQuery.extend( {
+ htmlPrefilter: function( html ) {
+ return html.replace( rxhtmlTag, "<$1></$2>" );
+ },
+
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var i, l, srcElements, destElements,
+ clone = elem.cloneNode( true ),
+ inPage = jQuery.contains( elem.ownerDocument, elem );
+
+ // Fix IE cloning issues
+ if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
+ !jQuery.isXMLDoc( elem ) ) {
- // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+ // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2
destElements = getAll( clone );
srcElements = getAll( elem );
- // Fix all IE cloning issues
- for ( i = 0; (node = srcElements[i]) != null; ++i ) {
- // Ensure that the destination node is not null; Fixes #9587
- if ( destElements[i] ) {
- fixCloneNodeIssues( node, destElements[i] );
- }
+ for ( i = 0, l = srcElements.length; i < l; i++ ) {
+ fixInput( srcElements[ i ], destElements[ i ] );
}
}
@@ -5516,8 +5730,8 @@ jQuery.extend({
srcElements = srcElements || getAll( elem );
destElements = destElements || getAll( clone );
- for ( i = 0; (node = srcElements[i]) != null; i++ ) {
- cloneCopyEvent( node, destElements[i] );
+ for ( i = 0, l = srcElements.length; i < l; i++ ) {
+ cloneCopyEvent( srcElements[ i ], destElements[ i ] );
}
} else {
cloneCopyEvent( elem, clone );
@@ -5530,154 +5744,18 @@ jQuery.extend({
setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
}
- destElements = srcElements = node = null;
-
// Return the cloned set
return clone;
},
- buildFragment: function( elems, context, scripts, selection ) {
- var j, elem, contains,
- tmp, tag, tbody, wrap,
- l = elems.length,
-
- // Ensure a safe fragment
- safe = createSafeFragment( context ),
-
- nodes = [],
+ cleanData: function( elems ) {
+ var data, elem, type,
+ special = jQuery.event.special,
i = 0;
- for ( ; i < l; i++ ) {
- elem = elems[ i ];
-
- if ( elem || elem === 0 ) {
-
- // Add nodes directly
- if ( jQuery.type( elem ) === "object" ) {
- jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
-
- // Convert non-html into a text node
- } else if ( !rhtml.test( elem ) ) {
- nodes.push( context.createTextNode( elem ) );
-
- // Convert html into DOM nodes
- } else {
- tmp = tmp || safe.appendChild( context.createElement("div") );
-
- // Deserialize a standard representation
- tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase();
- wrap = wrapMap[ tag ] || wrapMap._default;
-
- tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
-
- // Descend through wrappers to the right content
- j = wrap[0];
- while ( j-- ) {
- tmp = tmp.lastChild;
- }
-
- // Manually add leading whitespace removed by IE
- if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
- nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
- }
-
- // Remove IE's autoinserted <tbody> from table fragments
- if ( !support.tbody ) {
-
- // String was a <table>, *may* have spurious <tbody>
- elem = tag === "table" && !rtbody.test( elem ) ?
- tmp.firstChild :
-
- // String was a bare <thead> or <tfoot>
- wrap[1] === "<table>" && !rtbody.test( elem ) ?
- tmp :
- 0;
-
- j = elem && elem.childNodes.length;
- while ( j-- ) {
- if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
- elem.removeChild( tbody );
- }
- }
- }
-
- jQuery.merge( nodes, tmp.childNodes );
-
- // Fix #12392 for WebKit and IE > 9
- tmp.textContent = "";
-
- // Fix #12392 for oldIE
- while ( tmp.firstChild ) {
- tmp.removeChild( tmp.firstChild );
- }
-
- // Remember the top-level container for proper cleanup
- tmp = safe.lastChild;
- }
- }
- }
-
- // Fix #11356: Clear elements from fragment
- if ( tmp ) {
- safe.removeChild( tmp );
- }
-
- // Reset defaultChecked for any radios and checkboxes
- // about to be appended to the DOM in IE 6/7 (#8060)
- if ( !support.appendChecked ) {
- jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
- }
-
- i = 0;
- while ( (elem = nodes[ i++ ]) ) {
-
- // #4087 - If origin and destination elements are the same, and this is
- // that element, do not do anything
- if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
- continue;
- }
-
- contains = jQuery.contains( elem.ownerDocument, elem );
-
- // Append to fragment
- tmp = getAll( safe.appendChild( elem ), "script" );
-
- // Preserve script evaluation history
- if ( contains ) {
- setGlobalEval( tmp );
- }
-
- // Capture executables
- if ( scripts ) {
- j = 0;
- while ( (elem = tmp[ j++ ]) ) {
- if ( rscriptType.test( elem.type || "" ) ) {
- scripts.push( elem );
- }
- }
- }
- }
-
- tmp = null;
-
- return safe;
- },
-
- cleanData: function( elems, /* internal */ acceptData ) {
- var elem, type, id, data,
- i = 0,
- internalKey = jQuery.expando,
- cache = jQuery.cache,
- deleteExpando = support.deleteExpando,
- special = jQuery.event.special;
-
- for ( ; (elem = elems[i]) != null; i++ ) {
- if ( acceptData || jQuery.acceptData( elem ) ) {
-
- id = elem[ internalKey ];
- data = id && cache[ id ];
-
- if ( data ) {
+ for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
+ if ( acceptData( elem ) ) {
+ if ( ( data = elem[ dataPriv.expando ] ) ) {
if ( data.events ) {
for ( type in data.events ) {
if ( special[ type ] ) {
@@ -5690,116 +5768,88 @@ jQuery.extend({
}
}
- // Remove cache only if it was not already removed by jQuery.event.remove
- if ( cache[ id ] ) {
-
- delete cache[ id ];
-
- // IE does not allow us to delete expando properties from nodes,
- // nor does it have a removeAttribute function on Document nodes;
- // we must handle all of these cases
- if ( deleteExpando ) {
- delete elem[ internalKey ];
-
- } else if ( typeof elem.removeAttribute !== strundefined ) {
- elem.removeAttribute( internalKey );
-
- } else {
- elem[ internalKey ] = null;
- }
+ // Support: Chrome <=35 - 45+
+ // Assign undefined instead of using delete, see Data#remove
+ elem[ dataPriv.expando ] = undefined;
+ }
+ if ( elem[ dataUser.expando ] ) {
- deletedIds.push( id );
- }
+ // Support: Chrome <=35 - 45+
+ // Assign undefined instead of using delete, see Data#remove
+ elem[ dataUser.expando ] = undefined;
}
}
}
}
-});
+} );
+
+jQuery.fn.extend( {
+ detach: function( selector ) {
+ return remove( this, selector, true );
+ },
+
+ remove: function( selector ) {
+ return remove( this, selector );
+ },
-jQuery.fn.extend({
text: function( value ) {
return access( this, function( value ) {
return value === undefined ?
jQuery.text( this ) :
- this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+ this.empty().each( function() {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ this.textContent = value;
+ }
+ } );
}, null, value, arguments.length );
},
append: function() {
- return this.domManip( arguments, function( elem ) {
+ return domManip( this, arguments, function( elem ) {
if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
var target = manipulationTarget( this, elem );
target.appendChild( elem );
}
- });
+ } );
},
prepend: function() {
- return this.domManip( arguments, function( elem ) {
+ return domManip( this, arguments, function( elem ) {
if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
var target = manipulationTarget( this, elem );
target.insertBefore( elem, target.firstChild );
}
- });
+ } );
},
before: function() {
- return this.domManip( arguments, function( elem ) {
+ return domManip( this, arguments, function( elem ) {
if ( this.parentNode ) {
this.parentNode.insertBefore( elem, this );
}
- });
+ } );
},
after: function() {
- return this.domManip( arguments, function( elem ) {
+ return domManip( this, arguments, function( elem ) {
if ( this.parentNode ) {
this.parentNode.insertBefore( elem, this.nextSibling );
}
- });
- },
-
- remove: function( selector, keepData /* Internal Use Only */ ) {
- var elem,
- elems = selector ? jQuery.filter( selector, this ) : this,
- i = 0;
-
- for ( ; (elem = elems[i]) != null; i++ ) {
-
- if ( !keepData && elem.nodeType === 1 ) {
- jQuery.cleanData( getAll( elem ) );
- }
-
- if ( elem.parentNode ) {
- if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
- setGlobalEval( getAll( elem, "script" ) );
- }
- elem.parentNode.removeChild( elem );
- }
- }
-
- return this;
+ } );
},
empty: function() {
var elem,
i = 0;
- for ( ; (elem = this[i]) != null; i++ ) {
- // Remove element nodes and prevent memory leaks
+ for ( ; ( elem = this[ i ] ) != null; i++ ) {
if ( elem.nodeType === 1 ) {
- jQuery.cleanData( getAll( elem, false ) );
- }
- // Remove any remaining nodes
- while ( elem.firstChild ) {
- elem.removeChild( elem.firstChild );
- }
+ // Prevent memory leaks
+ jQuery.cleanData( getAll( elem, false ) );
- // If this is a select, ensure that it displays empty (#12336)
- // Support: IE<9
- if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
- elem.options.length = 0;
+ // Remove any remaining nodes
+ elem.textContent = "";
}
}
@@ -5810,9 +5860,9 @@ jQuery.fn.extend({
dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
- return this.map(function() {
+ return this.map( function() {
return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
- });
+ } );
},
html: function( value ) {
@@ -5821,24 +5871,21 @@ jQuery.fn.extend({
i = 0,
l = this.length;
- if ( value === undefined ) {
- return elem.nodeType === 1 ?
- elem.innerHTML.replace( rinlinejQuery, "" ) :
- undefined;
+ if ( value === undefined && elem.nodeType === 1 ) {
+ return elem.innerHTML;
}
// See if we can take a shortcut and just use innerHTML
if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
- ( support.htmlSerialize || !rnoshimcache.test( value ) ) &&
- ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
- !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {
+ !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
- value = value.replace( rxhtmlTag, "<$1></$2>" );
+ value = jQuery.htmlPrefilter( value );
try {
- for (; i < l; i++ ) {
+ for ( ; i < l; i++ ) {
+ elem = this[ i ] || {};
+
// Remove element nodes and prevent memory leaks
- elem = this[i] || {};
if ( elem.nodeType === 1 ) {
jQuery.cleanData( getAll( elem, false ) );
elem.innerHTML = value;
@@ -5848,7 +5895,7 @@ jQuery.fn.extend({
elem = 0;
// If using innerHTML throws an exception, use the fallback method
- } catch(e) {}
+ } catch ( e ) {}
}
if ( elem ) {
@@ -5858,117 +5905,25 @@ jQuery.fn.extend({
},
replaceWith: function() {
- var arg = arguments[ 0 ];
-
- // Make the changes, replacing each context element with the new content
- this.domManip( arguments, function( elem ) {
- arg = this.parentNode;
-
- jQuery.cleanData( getAll( this ) );
-
- if ( arg ) {
- arg.replaceChild( elem, this );
- }
- });
-
- // Force removal if there was no new content (e.g., from empty arguments)
- return arg && (arg.length || arg.nodeType) ? this : this.remove();
- },
-
- detach: function( selector ) {
- return this.remove( selector, true );
- },
-
- domManip: function( args, callback ) {
+ var ignored = [];
- // Flatten any nested arrays
- args = concat.apply( [], args );
+ // Make the changes, replacing each non-ignored context element with the new content
+ return domManip( this, arguments, function( elem ) {
+ var parent = this.parentNode;
- var first, node, hasScripts,
- scripts, doc, fragment,
- i = 0,
- l = this.length,
- set = this,
- iNoClone = l - 1,
- value = args[0],
- isFunction = jQuery.isFunction( value );
-
- // We can't cloneNode fragments that contain checked, in WebKit
- if ( isFunction ||
- ( l > 1 && typeof value === "string" &&
- !support.checkClone && rchecked.test( value ) ) ) {
- return this.each(function( index ) {
- var self = set.eq( index );
- if ( isFunction ) {
- args[0] = value.call( this, index, self.html() );
+ if ( jQuery.inArray( this, ignored ) < 0 ) {
+ jQuery.cleanData( getAll( this ) );
+ if ( parent ) {
+ parent.replaceChild( elem, this );
}
- self.domManip( args, callback );
- });
- }
-
- if ( l ) {
- fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
- first = fragment.firstChild;
-
- if ( fragment.childNodes.length === 1 ) {
- fragment = first;
}
- if ( first ) {
- scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
- hasScripts = scripts.length;
-
- // Use the original fragment for the last item instead of the first because it can end up
- // being emptied incorrectly in certain situations (#8070).
- for ( ; i < l; i++ ) {
- node = fragment;
-
- if ( i !== iNoClone ) {
- node = jQuery.clone( node, true, true );
-
- // Keep references to cloned scripts for later restoration
- if ( hasScripts ) {
- jQuery.merge( scripts, getAll( node, "script" ) );
- }
- }
-
- callback.call( this[i], node, i );
- }
-
- if ( hasScripts ) {
- doc = scripts[ scripts.length - 1 ].ownerDocument;
-
- // Reenable scripts
- jQuery.map( scripts, restoreScript );
-
- // Evaluate executable scripts on first document insertion
- for ( i = 0; i < hasScripts; i++ ) {
- node = scripts[ i ];
- if ( rscriptType.test( node.type || "" ) &&
- !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
-
- if ( node.src ) {
- // Optional AJAX dependency, but won't run scripts if not present
- if ( jQuery._evalUrl ) {
- jQuery._evalUrl( node.src );
- }
- } else {
- jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
- }
- }
- }
- }
-
- // Fix #11809: Avoid leaking memory
- fragment = first = null;
- }
- }
-
- return this;
+ // Force callback invocation
+ }, ignored );
}
-});
+} );
-jQuery.each({
+jQuery.each( {
appendTo: "append",
prependTo: "prepend",
insertBefore: "before",
@@ -5977,570 +5932,270 @@ jQuery.each({
}, function( name, original ) {
jQuery.fn[ name ] = function( selector ) {
var elems,
- i = 0,
ret = [],
insert = jQuery( selector ),
- last = insert.length - 1;
+ last = insert.length - 1,
+ i = 0;
for ( ; i <= last; i++ ) {
- elems = i === last ? this : this.clone(true);
- jQuery( insert[i] )[ original ]( elems );
+ elems = i === last ? this : this.clone( true );
+ jQuery( insert[ i ] )[ original ]( elems );
- // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // .get() because push.apply(_, arraylike) throws on ancient WebKit
push.apply( ret, elems.get() );
}
return this.pushStack( ret );
};
-});
-
-
-var iframe,
- elemdisplay = {};
-
-/**
- * Retrieve the actual display of a element
- * @param {String} name nodeName of the element
- * @param {Object} doc Document object
- */
-// Called only from within defaultDisplay
-function actualDisplay( name, doc ) {
- var style,
- elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
-
- // getDefaultComputedStyle might be reliably used only on attached element
- display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
-
- // Use of this method is a temporary fix (more like optmization) until something better comes along,
- // since it was removed from specification and supported only in FF
- style.display : jQuery.css( elem[ 0 ], "display" );
-
- // We don't have any data stored on the element,
- // so use "detach" method as fast way to get rid of the element
- elem.detach();
+} );
+var rmargin = ( /^margin/ );
- return display;
-}
-
-/**
- * Try to determine the default display value of an element
- * @param {String} nodeName
- */
-function defaultDisplay( nodeName ) {
- var doc = document,
- display = elemdisplay[ nodeName ];
-
- if ( !display ) {
- display = actualDisplay( nodeName, doc );
-
- // If the simple way fails, read from inside an iframe
- if ( display === "none" || !display ) {
-
- // Use the already-created iframe if possible
- iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
+var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
- // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
- doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;
+var getStyles = function( elem ) {
- // Support: IE
- doc.write();
- doc.close();
+ // Support: IE <=11 only, Firefox <=30 (#15098, #14150)
+ // IE throws on elements created in popups
+ // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
+ var view = elem.ownerDocument.defaultView;
- display = actualDisplay( nodeName, doc );
- iframe.detach();
+ if ( !view || !view.opener ) {
+ view = window;
}
- // Store the correct default display
- elemdisplay[ nodeName ] = display;
- }
-
- return display;
-}
-
+ return view.getComputedStyle( elem );
+ };
-(function() {
- var shrinkWrapBlocksVal;
- support.shrinkWrapBlocks = function() {
- if ( shrinkWrapBlocksVal != null ) {
- return shrinkWrapBlocksVal;
- }
- // Will be changed later if needed.
- shrinkWrapBlocksVal = false;
+( function() {
- // Minified: var b,c,d
- var div, body, container;
+ // Executing both pixelPosition & boxSizingReliable tests require only one layout
+ // so they're executed at the same time to save the second computation.
+ function computeStyleTests() {
- body = document.getElementsByTagName( "body" )[ 0 ];
- if ( !body || !body.style ) {
- // Test fired too early or in an unsupported environment, exit.
+ // This is a singleton, we need to execute it only once
+ if ( !div ) {
return;
}
- // Setup
- div = document.createElement( "div" );
- container = document.createElement( "div" );
- container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
- body.appendChild( container ).appendChild( div );
-
- // Support: IE6
- // Check if elements with layout shrink-wrap their children
- if ( typeof div.style.zoom !== strundefined ) {
- // Reset CSS: box-sizing; display; margin; border
- div.style.cssText =
- // Support: Firefox<29, Android 2.3
- // Vendor-prefix box-sizing
- "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
- "box-sizing:content-box;display:block;margin:0;border:0;" +
- "padding:1px;width:1px;zoom:1";
- div.appendChild( document.createElement( "div" ) ).style.width = "5px";
- shrinkWrapBlocksVal = div.offsetWidth !== 3;
- }
-
- body.removeChild( container );
-
- return shrinkWrapBlocksVal;
- };
-
-})();
-var rmargin = (/^margin/);
-
-var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
-
-
+ div.style.cssText =
+ "box-sizing:border-box;" +
+ "position:relative;display:block;" +
+ "margin:auto;border:1px;padding:1px;" +
+ "top:1%;width:50%";
+ div.innerHTML = "";
+ documentElement.appendChild( container );
-var getStyles, curCSS,
- rposition = /^(top|right|bottom|left)$/;
+ var divStyle = window.getComputedStyle( div );
+ pixelPositionVal = divStyle.top !== "1%";
-if ( window.getComputedStyle ) {
- getStyles = function( elem ) {
- return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
- };
+ // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
+ reliableMarginLeftVal = divStyle.marginLeft === "2px";
+ boxSizingReliableVal = divStyle.width === "4px";
- curCSS = function( elem, name, computed ) {
- var width, minWidth, maxWidth, ret,
- style = elem.style;
+ // Support: Android 4.0 - 4.3 only
+ // Some styles come back with percentage values, even though they shouldn't
+ div.style.marginRight = "50%";
+ pixelMarginRightVal = divStyle.marginRight === "4px";
- computed = computed || getStyles( elem );
+ documentElement.removeChild( container );
- // getPropertyValue is only needed for .css('filter') in IE9, see #12537
- ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
-
- if ( computed ) {
+ // Nullify the div so it wouldn't be stored in the memory and
+ // it will also be a sign that checks already performed
+ div = null;
+ }
- if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
- ret = jQuery.style( elem, name );
- }
+ var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
+ container = document.createElement( "div" ),
+ div = document.createElement( "div" );
- // A tribute to the "awesome hack by Dean Edwards"
- // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
- // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
- // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
- if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+ // Finish early in limited (non-browser) environments
+ if ( !div.style ) {
+ return;
+ }
- // Remember the original values
- width = style.width;
- minWidth = style.minWidth;
- maxWidth = style.maxWidth;
+ // Support: IE <=9 - 11 only
+ // Style of cloned element affects source element cloned (#8908)
+ div.style.backgroundClip = "content-box";
+ div.cloneNode( true ).style.backgroundClip = "";
+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
- // Put in the new values to get a computed value out
- style.minWidth = style.maxWidth = style.width = ret;
- ret = computed.width;
+ container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
+ "padding:0;margin-top:1px;position:absolute";
+ container.appendChild( div );
- // Revert the changed values
- style.width = width;
- style.minWidth = minWidth;
- style.maxWidth = maxWidth;
- }
+ jQuery.extend( support, {
+ pixelPosition: function() {
+ computeStyleTests();
+ return pixelPositionVal;
+ },
+ boxSizingReliable: function() {
+ computeStyleTests();
+ return boxSizingReliableVal;
+ },
+ pixelMarginRight: function() {
+ computeStyleTests();
+ return pixelMarginRightVal;
+ },
+ reliableMarginLeft: function() {
+ computeStyleTests();
+ return reliableMarginLeftVal;
}
+ } );
+} )();
- // Support: IE
- // IE returns zIndex value as an integer.
- return ret === undefined ?
- ret :
- ret + "";
- };
-} else if ( document.documentElement.currentStyle ) {
- getStyles = function( elem ) {
- return elem.currentStyle;
- };
- curCSS = function( elem, name, computed ) {
- var left, rs, rsLeft, ret,
- style = elem.style;
+function curCSS( elem, name, computed ) {
+ var width, minWidth, maxWidth, ret,
+ style = elem.style;
- computed = computed || getStyles( elem );
- ret = computed ? computed[ name ] : undefined;
+ computed = computed || getStyles( elem );
- // Avoid setting ret to empty string here
- // so we don't default to auto
- if ( ret == null && style && style[ name ] ) {
- ret = style[ name ];
- }
+ // Support: IE <=9 only
+ // getPropertyValue is only needed for .css('filter') (#12537)
+ if ( computed ) {
+ ret = computed.getPropertyValue( name ) || computed[ name ];
- // From the awesome hack by Dean Edwards
- // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
- // If we're not dealing with a regular pixel number
- // but a number that has a weird ending, we need to convert it to pixels
- // but not position css attributes, as those are proportional to the parent element instead
- // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
- if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
+ // A tribute to the "awesome hack by Dean Edwards"
+ // Android Browser returns percentage for some values,
+ // but width seems to be reliably pixels.
+ // This is against the CSSOM draft spec:
+ // https://drafts.csswg.org/cssom/#resolved-values
+ if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {
// Remember the original values
- left = style.left;
- rs = elem.runtimeStyle;
- rsLeft = rs && rs.left;
+ width = style.width;
+ minWidth = style.minWidth;
+ maxWidth = style.maxWidth;
// Put in the new values to get a computed value out
- if ( rsLeft ) {
- rs.left = elem.currentStyle.left;
- }
- style.left = name === "fontSize" ? "1em" : ret;
- ret = style.pixelLeft + "px";
+ style.minWidth = style.maxWidth = style.width = ret;
+ ret = computed.width;
// Revert the changed values
- style.left = left;
- if ( rsLeft ) {
- rs.left = rsLeft;
- }
+ style.width = width;
+ style.minWidth = minWidth;
+ style.maxWidth = maxWidth;
}
+ }
+
+ return ret !== undefined ?
- // Support: IE
+ // Support: IE <=9 - 11 only
// IE returns zIndex value as an integer.
- return ret === undefined ?
- ret :
- ret + "" || "auto";
- };
+ ret + "" :
+ ret;
}
-
-
function addGetHookIf( conditionFn, hookFn ) {
+
// Define the hook, we'll check on the first run if it's really needed.
return {
get: function() {
- var condition = conditionFn();
+ if ( conditionFn() ) {
- if ( condition == null ) {
- // The test was not ready at this point; screw the hook this time
- // but check again when needed next time.
- return;
- }
-
- if ( condition ) {
- // Hook not needed (or it's not possible to use it due to missing dependency),
- // remove it.
- // Since there are no other hooks for marginRight, remove the whole object.
+ // Hook not needed (or it's not possible to use it due
+ // to missing dependency), remove it.
delete this.get;
return;
}
// Hook needed; redefine it so that the support test is not executed again.
-
- return (this.get = hookFn).apply( this, arguments );
+ return ( this.get = hookFn ).apply( this, arguments );
}
};
}
-(function() {
- // Minified: var b,c,d,e,f,g, h,i
- var div, style, a, pixelPositionVal, boxSizingReliableVal,
- reliableHiddenOffsetsVal, reliableMarginRightVal;
-
- // Setup
- div = document.createElement( "div" );
- div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
- a = div.getElementsByTagName( "a" )[ 0 ];
- style = a && a.style;
-
- // Finish early in limited (non-browser) environments
- if ( !style ) {
- return;
- }
-
- style.cssText = "float:left;opacity:.5";
-
- // Support: IE<9
- // Make sure that element opacity exists (as opposed to filter)
- support.opacity = style.opacity === "0.5";
-
- // Verify style float existence
- // (IE uses styleFloat instead of cssFloat)
- support.cssFloat = !!style.cssFloat;
-
- div.style.backgroundClip = "content-box";
- div.cloneNode( true ).style.backgroundClip = "";
- support.clearCloneStyle = div.style.backgroundClip === "content-box";
-
- // Support: Firefox<29, Android 2.3
- // Vendor-prefix box-sizing
- support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" ||
- style.WebkitBoxSizing === "";
-
- jQuery.extend(support, {
- reliableHiddenOffsets: function() {
- if ( reliableHiddenOffsetsVal == null ) {
- computeStyleTests();
- }
- return reliableHiddenOffsetsVal;
- },
-
- boxSizingReliable: function() {
- if ( boxSizingReliableVal == null ) {
- computeStyleTests();
- }
- return boxSizingReliableVal;
- },
-
- pixelPosition: function() {
- if ( pixelPositionVal == null ) {
- computeStyleTests();
- }
- return pixelPositionVal;
- },
-
- // Support: Android 2.3
- reliableMarginRight: function() {
- if ( reliableMarginRightVal == null ) {
- computeStyleTests();
- }
- return reliableMarginRightVal;
- }
- });
-
- function computeStyleTests() {
- // Minified: var b,c,d,j
- var div, body, container, contents;
-
- body = document.getElementsByTagName( "body" )[ 0 ];
- if ( !body || !body.style ) {
- // Test fired too early or in an unsupported environment, exit.
- return;
- }
-
- // Setup
- div = document.createElement( "div" );
- container = document.createElement( "div" );
- container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
- body.appendChild( container ).appendChild( div );
-
- div.style.cssText =
- // Support: Firefox<29, Android 2.3
- // Vendor-prefix box-sizing
- "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
- "box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
- "border:1px;padding:1px;width:4px;position:absolute";
-
- // Support: IE<9
- // Assume reasonable values in the absence of getComputedStyle
- pixelPositionVal = boxSizingReliableVal = false;
- reliableMarginRightVal = true;
-
- // Check for getComputedStyle so that this code is not run in IE<9.
- if ( window.getComputedStyle ) {
- pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
- boxSizingReliableVal =
- ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
-
- // Support: Android 2.3
- // Div with explicit width and no margin-right incorrectly
- // gets computed margin-right based on width of container (#3333)
- // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
- contents = div.appendChild( document.createElement( "div" ) );
-
- // Reset CSS: box-sizing; display; margin; border; padding
- contents.style.cssText = div.style.cssText =
- // Support: Firefox<29, Android 2.3
- // Vendor-prefix box-sizing
- "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
- "box-sizing:content-box;display:block;margin:0;border:0;padding:0";
- contents.style.marginRight = contents.style.width = "0";
- div.style.width = "1px";
-
- reliableMarginRightVal =
- !parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );
- }
-
- // Support: IE8
- // Check if table cells still have offsetWidth/Height when they are set
- // to display:none and there are still other visible table cells in a
- // table row; if so, offsetWidth/Height are not reliable for use when
- // determining if an element has been hidden directly using
- // display:none (it is still safe to use offsets if a parent element is
- // hidden; don safety goggles and see bug #4512 for more information).
- div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
- contents = div.getElementsByTagName( "td" );
- contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none";
- reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
- if ( reliableHiddenOffsetsVal ) {
- contents[ 0 ].style.display = "";
- contents[ 1 ].style.display = "none";
- reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
- }
-
- body.removeChild( container );
- }
-
-})();
-
-
-// A method for quickly swapping in/out CSS properties to get correct calculations.
-jQuery.swap = function( elem, options, callback, args ) {
- var ret, name,
- old = {};
-
- // Remember the old values, and insert the new ones
- for ( name in options ) {
- old[ name ] = elem.style[ name ];
- elem.style[ name ] = options[ name ];
- }
-
- ret = callback.apply( elem, args || [] );
-
- // Revert the old values
- for ( name in options ) {
- elem.style[ name ] = old[ name ];
- }
-
- return ret;
-};
-
-
var
- ralpha = /alpha\([^)]*\)/i,
- ropacity = /opacity\s*=\s*([^)]*)/,
- // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
- // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+ // Swappable if display is none or starts with table
+ // except "table", "table-cell", or "table-caption"
+ // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
rdisplayswap = /^(none|table(?!-c[ea]).+)/,
- rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
- rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
-
cssShow = { position: "absolute", visibility: "hidden", display: "block" },
cssNormalTransform = {
letterSpacing: "0",
fontWeight: "400"
},
- cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
-
+ cssPrefixes = [ "Webkit", "Moz", "ms" ],
+ emptyStyle = document.createElement( "div" ).style;
-// return a css property mapped to a potentially vendor prefixed property
-function vendorPropName( style, name ) {
+// Return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( name ) {
- // shortcut for names that are not vendor prefixed
- if ( name in style ) {
+ // Shortcut for names that are not vendor prefixed
+ if ( name in emptyStyle ) {
return name;
}
- // check for vendor prefixed names
- var capName = name.charAt(0).toUpperCase() + name.slice(1),
- origName = name,
+ // Check for vendor prefixed names
+ var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
i = cssPrefixes.length;
while ( i-- ) {
name = cssPrefixes[ i ] + capName;
- if ( name in style ) {
+ if ( name in emptyStyle ) {
return name;
}
}
-
- return origName;
-}
-
-function showHide( elements, show ) {
- var display, elem, hidden,
- values = [],
- index = 0,
- length = elements.length;
-
- for ( ; index < length; index++ ) {
- elem = elements[ index ];
- if ( !elem.style ) {
- continue;
- }
-
- values[ index ] = jQuery._data( elem, "olddisplay" );
- display = elem.style.display;
- if ( show ) {
- // Reset the inline display of this element to learn if it is
- // being hidden by cascaded rules or not
- if ( !values[ index ] && display === "none" ) {
- elem.style.display = "";
- }
-
- // Set elements which have been overridden with display: none
- // in a stylesheet to whatever the default browser style is
- // for such an element
- if ( elem.style.display === "" && isHidden( elem ) ) {
- values[ index ] = jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
- }
- } else {
- hidden = isHidden( elem );
-
- if ( display && display !== "none" || !hidden ) {
- jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
- }
- }
- }
-
- // Set the display of most of the elements in a second loop
- // to avoid the constant reflow
- for ( index = 0; index < length; index++ ) {
- elem = elements[ index ];
- if ( !elem.style ) {
- continue;
- }
- if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
- elem.style.display = show ? values[ index ] || "" : "none";
- }
- }
-
- return elements;
}
function setPositiveNumber( elem, value, subtract ) {
- var matches = rnumsplit.exec( value );
+
+ // Any relative (+/-) values have already been
+ // normalized at this point
+ var matches = rcssNum.exec( value );
return matches ?
+
// Guard against undefined "subtract", e.g., when used as in cssHooks
- Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+ Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
value;
}
function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
var i = extra === ( isBorderBox ? "border" : "content" ) ?
+
// If we already have the right measurement, avoid augmentation
4 :
+
// Otherwise initialize for horizontal or vertical properties
name === "width" ? 1 : 0,
val = 0;
for ( ; i < 4; i += 2 ) {
- // both box models exclude margin, so add it if we want it
+
+ // Both box models exclude margin, so add it if we want it
if ( extra === "margin" ) {
val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
}
if ( isBorderBox ) {
+
// border-box includes padding, so remove it if we want content
if ( extra === "content" ) {
val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
}
- // at this point, extra isn't border nor margin, so remove border
+ // At this point, extra isn't border nor margin, so remove border
if ( extra !== "margin" ) {
val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
}
} else {
- // at this point, extra isn't content, so add padding
+
+ // At this point, extra isn't content, so add padding
val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
- // at this point, extra isn't content nor padding, so add border
+ // At this point, extra isn't content nor padding, so add border
if ( extra !== "padding" ) {
val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
}
@@ -6553,15 +6208,23 @@ function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
function getWidthOrHeight( elem, name, extra ) {
// Start with offset property, which is equivalent to the border-box value
- var valueIsBorderBox = true,
- val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+ var val,
+ valueIsBorderBox = true,
styles = getStyles( elem ),
- isBorderBox = support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+ isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
- // some non-html elements return undefined for offsetWidth, so check for null/undefined
+ // Support: IE <=11 only
+ // Running getBoundingClientRect on a disconnected node
+ // in IE throws an error.
+ if ( elem.getClientRects().length ) {
+ val = elem.getBoundingClientRect()[ name ];
+ }
+
+ // Some non-html elements return undefined for offsetWidth, so check for null/undefined
// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
if ( val <= 0 || val == null ) {
+
// Fall back to computed then uncomputed css if necessary
val = curCSS( elem, name, styles );
if ( val < 0 || val == null ) {
@@ -6569,19 +6232,20 @@ function getWidthOrHeight( elem, name, extra ) {
}
// Computed unit is not pixels. Stop here and return.
- if ( rnumnonpx.test(val) ) {
+ if ( rnumnonpx.test( val ) ) {
return val;
}
- // we need the check for style in case a browser which returns unreliable values
+ // Check for style in case a browser which returns unreliable values
// for getComputedStyle silently falls back to the reliable elem.style
- valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );
+ valueIsBorderBox = isBorderBox &&
+ ( support.boxSizingReliable() || val === elem.style[ name ] );
// Normalize "", auto, and prepare for extra
val = parseFloat( val ) || 0;
}
- // use the active box-sizing model to add/subtract irrelevant styles
+ // Use the active box-sizing model to add/subtract irrelevant styles
return ( val +
augmentWidthOrHeight(
elem,
@@ -6593,13 +6257,15 @@ function getWidthOrHeight( elem, name, extra ) {
) + "px";
}
-jQuery.extend({
+jQuery.extend( {
+
// Add in style property hooks for overriding the default
// behavior of getting and setting a style property
cssHooks: {
opacity: {
get: function( elem, computed ) {
if ( computed ) {
+
// We should always get a number back from opacity
var ret = curCSS( elem, "opacity" );
return ret === "" ? "1" : ret;
@@ -6610,6 +6276,7 @@ jQuery.extend({
// Don't automatically add "px" to these possibly-unitless properties
cssNumber: {
+ "animationIterationCount": true,
"columnCount": true,
"fillOpacity": true,
"flexGrow": true,
@@ -6627,12 +6294,12 @@ jQuery.extend({
// Add in properties whose names you wish to fix before
// setting or getting the value
cssProps: {
- // normalize float css property
- "float": support.cssFloat ? "cssFloat" : "styleFloat"
+ "float": "cssFloat"
},
// Get and set the style property on a DOM Node
style: function( elem, name, value, extra ) {
+
// Don't set styles on text and comment nodes
if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
return;
@@ -6643,52 +6310,52 @@ jQuery.extend({
origName = jQuery.camelCase( name ),
style = elem.style;
- name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+ name = jQuery.cssProps[ origName ] ||
+ ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
- // gets hook for the prefixed version
- // followed by the unprefixed version
+ // Gets hook for the prefixed version, then unprefixed version
hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
// Check if we're setting a value
if ( value !== undefined ) {
type = typeof value;
- // convert relative number strings (+= or -=) to relative numbers. #7345
- if ( type === "string" && (ret = rrelNum.exec( value )) ) {
- value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+ // Convert "+=" or "-=" to relative numbers (#7345)
+ if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
+ value = adjustCSS( elem, name, ret );
+
// Fixes bug #9237
type = "number";
}
- // Make sure that null and NaN values aren't set. See: #7116
+ // Make sure that null and NaN values aren't set (#7116)
if ( value == null || value !== value ) {
return;
}
- // If a number was passed in, add 'px' to the (except for certain CSS properties)
- if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
- value += "px";
+ // If a number was passed in, add the unit (except for certain CSS properties)
+ if ( type === "number" ) {
+ value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
}
- // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
- // but it would mean to define eight (for every problematic property) identical functions
- if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
+ // background-* props affect original clone's values
+ if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
style[ name ] = "inherit";
}
// If a hook was provided, use that value, otherwise just set the specified value
- if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+ if ( !hooks || !( "set" in hooks ) ||
+ ( value = hooks.set( elem, value, extra ) ) !== undefined ) {
- // Support: IE
- // Swallow errors from 'invalid' CSS values (#5509)
- try {
- style[ name ] = value;
- } catch(e) {}
+ style[ name ] = value;
}
} else {
+
// If a hook was provided get the non-computed value from there
- if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+ if ( hooks && "get" in hooks &&
+ ( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
+
return ret;
}
@@ -6698,14 +6365,14 @@ jQuery.extend({
},
css: function( elem, name, extra, styles ) {
- var num, val, hooks,
+ var val, num, hooks,
origName = jQuery.camelCase( name );
// Make sure that we're working with the right name
- name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+ name = jQuery.cssProps[ origName ] ||
+ ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
- // gets hook for the prefixed version
- // followed by the unprefixed version
+ // Try prefixed name followed by the unprefixed name
hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
// If a hook was provided get the computed value from there
@@ -6718,106 +6385,82 @@ jQuery.extend({
val = curCSS( elem, name, styles );
}
- //convert "normal" to computed value
+ // Convert "normal" to computed value
if ( val === "normal" && name in cssNormalTransform ) {
val = cssNormalTransform[ name ];
}
- // Return, converting to number if forced or a qualifier was provided and val looks numeric
+ // Make numeric if forced or a qualifier was provided and val looks numeric
if ( extra === "" || extra ) {
num = parseFloat( val );
- return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
+ return extra === true || isFinite( num ) ? num || 0 : val;
}
return val;
}
-});
+} );
-jQuery.each([ "height", "width" ], function( i, name ) {
+jQuery.each( [ "height", "width" ], function( i, name ) {
jQuery.cssHooks[ name ] = {
get: function( elem, computed, extra ) {
if ( computed ) {
- // certain elements can have dimension info if we invisibly show them
- // however, it must have a current display style that would benefit from this
- return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
- jQuery.swap( elem, cssShow, function() {
- return getWidthOrHeight( elem, name, extra );
- }) :
- getWidthOrHeight( elem, name, extra );
+
+ // Certain elements can have dimension info if we invisibly show them
+ // but it must have a current display style that would benefit
+ return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
+
+ // Support: Safari 8+
+ // Table columns in Safari have non-zero offsetWidth & zero
+ // getBoundingClientRect().width unless display is changed.
+ // Support: IE <=11 only
+ // Running getBoundingClientRect on a disconnected node
+ // in IE throws an error.
+ ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
+ swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ } ) :
+ getWidthOrHeight( elem, name, extra );
}
},
set: function( elem, value, extra ) {
- var styles = extra && getStyles( elem );
- return setPositiveNumber( elem, value, extra ?
- augmentWidthOrHeight(
+ var matches,
+ styles = extra && getStyles( elem ),
+ subtract = extra && augmentWidthOrHeight(
elem,
name,
extra,
- support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+ jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
styles
- ) : 0
- );
- }
- };
-});
+ );
-if ( !support.opacity ) {
- jQuery.cssHooks.opacity = {
- get: function( elem, computed ) {
- // IE uses filters for opacity
- return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
- ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
- computed ? "1" : "";
- },
+ // Convert to pixels if value adjustment is needed
+ if ( subtract && ( matches = rcssNum.exec( value ) ) &&
+ ( matches[ 3 ] || "px" ) !== "px" ) {
- set: function( elem, value ) {
- var style = elem.style,
- currentStyle = elem.currentStyle,
- opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
- filter = currentStyle && currentStyle.filter || style.filter || "";
-
- // IE has trouble with opacity if it does not have layout
- // Force it by setting the zoom level
- style.zoom = 1;
-
- // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
- // if value === "", then remove inline opacity #12685
- if ( ( value >= 1 || value === "" ) &&
- jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
- style.removeAttribute ) {
-
- // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
- // if "filter:" is present at all, clearType is disabled, we want to avoid this
- // style.removeAttribute is IE Only, but so apparently is this code path...
- style.removeAttribute( "filter" );
-
- // if there is no filter style applied in a css rule or unset inline opacity, we are done
- if ( value === "" || currentStyle && !currentStyle.filter ) {
- return;
- }
+ elem.style[ name ] = value;
+ value = jQuery.css( elem, name );
}
- // otherwise, set new filter values
- style.filter = ralpha.test( filter ) ?
- filter.replace( ralpha, opacity ) :
- filter + " " + opacity;
+ return setPositiveNumber( elem, value, subtract );
}
};
-}
+} );
-jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
+jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
function( elem, computed ) {
if ( computed ) {
- // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
- // Work around by temporarily setting element display to inline-block
- return jQuery.swap( elem, { "display": "inline-block" },
- curCSS, [ elem, "marginRight" ] );
+ return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
+ elem.getBoundingClientRect().left -
+ swap( elem, { marginLeft: 0 }, function() {
+ return elem.getBoundingClientRect().left;
+ } )
+ ) + "px";
}
}
);
// These hooks are used by animate to expand properties
-jQuery.each({
+jQuery.each( {
margin: "",
padding: "",
border: "Width"
@@ -6827,8 +6470,8 @@ jQuery.each({
var i = 0,
expanded = {},
- // assumes a single number if not a string
- parts = typeof value === "string" ? value.split(" ") : [ value ];
+ // Assumes a single number if not a string
+ parts = typeof value === "string" ? value.split( " " ) : [ value ];
for ( ; i < 4; i++ ) {
expanded[ prefix + cssExpand[ i ] + suffix ] =
@@ -6842,9 +6485,9 @@ jQuery.each({
if ( !rmargin.test( prefix ) ) {
jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
}
-});
+} );
-jQuery.fn.extend({
+jQuery.fn.extend( {
css: function( name, value ) {
return access( this, function( elem, name, value ) {
var styles, len,
@@ -6866,27 +6509,8 @@ jQuery.fn.extend({
jQuery.style( elem, name, value ) :
jQuery.css( elem, name );
}, name, value, arguments.length > 1 );
- },
- show: function() {
- return showHide( this, true );
- },
- hide: function() {
- return showHide( this );
- },
- toggle: function( state ) {
- if ( typeof state === "boolean" ) {
- return state ? this.show() : this.hide();
- }
-
- return this.each(function() {
- if ( isHidden( this ) ) {
- jQuery( this ).show();
- } else {
- jQuery( this ).hide();
- }
- });
}
-});
+} );
function Tween( elem, options, prop, end, easing ) {
@@ -6899,7 +6523,7 @@ Tween.prototype = {
init: function( elem, options, prop, end, easing, unit ) {
this.elem = elem;
this.prop = prop;
- this.easing = easing || "swing";
+ this.easing = easing || jQuery.easing._default;
this.options = options;
this.start = this.now = this.cur();
this.end = end;
@@ -6945,25 +6569,32 @@ Tween.propHooks = {
get: function( tween ) {
var result;
- if ( tween.elem[ tween.prop ] != null &&
- (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+ // Use a property on the element directly when it is not a DOM element,
+ // or when there is no matching style property that exists.
+ if ( tween.elem.nodeType !== 1 ||
+ tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
return tween.elem[ tween.prop ];
}
- // passing an empty string as a 3rd parameter to .css will automatically
- // attempt a parseFloat and fallback to a string if the parse fails
- // so, simple values such as "10px" are parsed to Float.
- // complex values such as "rotate(1rad)" are returned as is.
+ // Passing an empty string as a 3rd parameter to .css will automatically
+ // attempt a parseFloat and fallback to a string if the parse fails.
+ // Simple values such as "10px" are parsed to Float;
+ // complex values such as "rotate(1rad)" are returned as-is.
result = jQuery.css( tween.elem, tween.prop, "" );
+
// Empty strings, null, undefined and "auto" are converted to 0.
return !result || result === "auto" ? 0 : result;
},
set: function( tween ) {
- // use step hook for back compat - use cssHook if its there - use .style if its
- // available and use plain properties where available
+
+ // Use step hook for back compat.
+ // Use cssHook if its there.
+ // Use .style if available and use plain properties where available.
if ( jQuery.fx.step[ tween.prop ] ) {
jQuery.fx.step[ tween.prop ]( tween );
- } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+ } else if ( tween.elem.nodeType === 1 &&
+ ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
+ jQuery.cssHooks[ tween.prop ] ) ) {
jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
} else {
tween.elem[ tween.prop ] = tween.now;
@@ -6972,9 +6603,8 @@ Tween.propHooks = {
}
};
-// Support: IE <=9
+// Support: IE <=9 only
// Panic based approach to setting things on disconnected nodes
-
Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
set: function( tween ) {
if ( tween.elem.nodeType && tween.elem.parentNode ) {
@@ -6989,12 +6619,13 @@ jQuery.easing = {
},
swing: function( p ) {
return 0.5 - Math.cos( p * Math.PI ) / 2;
- }
+ },
+ _default: "swing"
};
jQuery.fx = Tween.prototype.init;
-// Back Compat <1.8 extension point
+// Back compat <1.8 extension point
jQuery.fx.step = {};
@@ -7003,78 +6634,33 @@ jQuery.fx.step = {};
var
fxNow, timerId,
rfxtypes = /^(?:toggle|show|hide)$/,
- rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
- rrun = /queueHooks$/,
- animationPrefilters = [ defaultPrefilter ],
- tweeners = {
- "*": [ function( prop, value ) {
- var tween = this.createTween( prop, value ),
- target = tween.cur(),
- parts = rfxnum.exec( value ),
- unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
-
- // Starting value computation is required for potential unit mismatches
- start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
- rfxnum.exec( jQuery.css( tween.elem, prop ) ),
- scale = 1,
- maxIterations = 20;
+ rrun = /queueHooks$/;
- if ( start && start[ 3 ] !== unit ) {
- // Trust units reported by jQuery.css
- unit = unit || start[ 3 ];
-
- // Make sure we update the tween properties later on
- parts = parts || [];
-
- // Iteratively approximate from a nonzero starting point
- start = +target || 1;
-
- do {
- // If previous iteration zeroed out, double until we get *something*
- // Use a string for doubling factor so we don't accidentally see scale as unchanged below
- scale = scale || ".5";
-
- // Adjust and apply
- start = start / scale;
- jQuery.style( tween.elem, prop, start + unit );
-
- // Update scale, tolerating zero or NaN from tween.cur()
- // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
- } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
- }
-
- // Update tween properties
- if ( parts ) {
- start = tween.start = +start || +target || 0;
- tween.unit = unit;
- // If a +=/-= token was provided, we're doing a relative animation
- tween.end = parts[ 1 ] ?
- start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
- +parts[ 2 ];
- }
-
- return tween;
- } ]
- };
+function raf() {
+ if ( timerId ) {
+ window.requestAnimationFrame( raf );
+ jQuery.fx.tick();
+ }
+}
// Animations created synchronously will run synchronously
function createFxNow() {
- setTimeout(function() {
+ window.setTimeout( function() {
fxNow = undefined;
- });
+ } );
return ( fxNow = jQuery.now() );
}
// Generate parameters to create a standard animation
function genFx( type, includeWidth ) {
var which,
- attrs = { height: type },
- i = 0;
+ i = 0,
+ attrs = { height: type };
- // if we include width, step value is 1 to do all cssExpand values,
- // if we don't include width, step value is 2 to skip over Left and Right
+ // If we include width, step value is 1 to do all cssExpand values,
+ // otherwise step value is 2 to skip over Left and Right
includeWidth = includeWidth ? 1 : 0;
- for ( ; i < 4 ; i += 2 - includeWidth ) {
+ for ( ; i < 4; i += 2 - includeWidth ) {
which = cssExpand[ i ];
attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
}
@@ -7088,28 +6674,28 @@ function genFx( type, includeWidth ) {
function createTween( value, prop, animation ) {
var tween,
- collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+ collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
index = 0,
length = collection.length;
for ( ; index < length; index++ ) {
- if ( (tween = collection[ index ].call( animation, prop, value )) ) {
+ if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
- // we're done with this property
+ // We're done with this property
return tween;
}
}
}
function defaultPrefilter( elem, props, opts ) {
- /* jshint validthis: true */
- var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
+ var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
+ isBox = "width" in props || "height" in props,
anim = this,
orig = {},
style = elem.style,
- hidden = elem.nodeType && isHidden( elem ),
- dataShow = jQuery._data( elem, "fxshow" );
+ hidden = elem.nodeType && isHiddenWithinTree( elem ),
+ dataShow = dataPriv.get( elem, "fxshow" );
- // handle queue: false promises
+ // Queue-skipping animations hijack the fx hooks
if ( !opts.queue ) {
hooks = jQuery._queueHooks( elem, "fx" );
if ( hooks.unqueued == null ) {
@@ -7123,122 +6709,151 @@ function defaultPrefilter( elem, props, opts ) {
}
hooks.unqueued++;
- anim.always(function() {
- // doing this makes sure that the complete handler will be called
- // before this completes
- anim.always(function() {
+ anim.always( function() {
+
+ // Ensure the complete handler is called before this completes
+ anim.always( function() {
hooks.unqueued--;
if ( !jQuery.queue( elem, "fx" ).length ) {
hooks.empty.fire();
}
- });
- });
- }
-
- // height/width overflow pass
- if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
- // Make sure that nothing sneaks out
- // Record all 3 overflow attributes because IE does not
- // change the overflow attribute when overflowX and
- // overflowY are set to the same value
- opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
-
- // Set display property to inline-block for height/width
- // animations on inline elements that are having width/height animated
- display = jQuery.css( elem, "display" );
-
- // Test default display if display is currently "none"
- checkDisplay = display === "none" ?
- jQuery._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
-
- if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
-
- // inline-level elements accept inline-block;
- // block-level elements need to be inline with layout
- if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) {
- style.display = "inline-block";
- } else {
- style.zoom = 1;
- }
- }
+ } );
+ } );
}
- if ( opts.overflow ) {
- style.overflow = "hidden";
- if ( !support.shrinkWrapBlocks() ) {
- anim.always(function() {
- style.overflow = opts.overflow[ 0 ];
- style.overflowX = opts.overflow[ 1 ];
- style.overflowY = opts.overflow[ 2 ];
- });
- }
- }
-
- // show/hide pass
+ // Detect show/hide animations
for ( prop in props ) {
value = props[ prop ];
- if ( rfxtypes.exec( value ) ) {
+ if ( rfxtypes.test( value ) ) {
delete props[ prop ];
toggle = toggle || value === "toggle";
if ( value === ( hidden ? "hide" : "show" ) ) {
- // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
+ // Pretend to be hidden if this is a "show" and
+ // there is still data from a stopped show/hide
if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
hidden = true;
+
+ // Ignore all other no-op show/hide data
} else {
continue;
}
}
orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
-
- // Any non-fx value stops us from restoring the original display value
- } else {
- display = undefined;
}
}
- if ( !jQuery.isEmptyObject( orig ) ) {
- if ( dataShow ) {
- if ( "hidden" in dataShow ) {
- hidden = dataShow.hidden;
- }
- } else {
- dataShow = jQuery._data( elem, "fxshow", {} );
- }
+ // Bail out if this is a no-op like .hide().hide()
+ propTween = !jQuery.isEmptyObject( props );
+ if ( !propTween && jQuery.isEmptyObject( orig ) ) {
+ return;
+ }
+
+ // Restrict "overflow" and "display" styles during box animations
+ if ( isBox && elem.nodeType === 1 ) {
+
+ // Support: IE <=9 - 11, Edge 12 - 13
+ // Record all 3 overflow attributes because IE does not infer the shorthand
+ // from identically-valued overflowX and overflowY
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
- // store state if its toggle - enables .stop().toggle() to "reverse"
- if ( toggle ) {
- dataShow.hidden = !hidden;
+ // Identify a display type, preferring old show/hide data over the CSS cascade
+ restoreDisplay = dataShow && dataShow.display;
+ if ( restoreDisplay == null ) {
+ restoreDisplay = dataPriv.get( elem, "display" );
}
- if ( hidden ) {
- jQuery( elem ).show();
- } else {
- anim.done(function() {
- jQuery( elem ).hide();
- });
+ display = jQuery.css( elem, "display" );
+ if ( display === "none" ) {
+ if ( restoreDisplay ) {
+ display = restoreDisplay;
+ } else {
+
+ // Get nonempty value(s) by temporarily forcing visibility
+ showHide( [ elem ], true );
+ restoreDisplay = elem.style.display || restoreDisplay;
+ display = jQuery.css( elem, "display" );
+ showHide( [ elem ] );
+ }
}
- anim.done(function() {
- var prop;
- jQuery._removeData( elem, "fxshow" );
- for ( prop in orig ) {
- jQuery.style( elem, prop, orig[ prop ] );
+
+ // Animate inline elements as inline-block
+ if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
+ if ( jQuery.css( elem, "float" ) === "none" ) {
+
+ // Restore the original display value at the end of pure show/hide animations
+ if ( !propTween ) {
+ anim.done( function() {
+ style.display = restoreDisplay;
+ } );
+ if ( restoreDisplay == null ) {
+ display = style.display;
+ restoreDisplay = display === "none" ? "" : display;
+ }
+ }
+ style.display = "inline-block";
}
- });
- for ( prop in orig ) {
- tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
-
- if ( !( prop in dataShow ) ) {
- dataShow[ prop ] = tween.start;
- if ( hidden ) {
- tween.end = tween.start;
- tween.start = prop === "width" || prop === "height" ? 1 : 0;
+ }
+ }
+
+ if ( opts.overflow ) {
+ style.overflow = "hidden";
+ anim.always( function() {
+ style.overflow = opts.overflow[ 0 ];
+ style.overflowX = opts.overflow[ 1 ];
+ style.overflowY = opts.overflow[ 2 ];
+ } );
+ }
+
+ // Implement show/hide animations
+ propTween = false;
+ for ( prop in orig ) {
+
+ // General show/hide setup for this element animation
+ if ( !propTween ) {
+ if ( dataShow ) {
+ if ( "hidden" in dataShow ) {
+ hidden = dataShow.hidden;
}
+ } else {
+ dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
}
+
+ // Store hidden/visible for toggle so `.stop().toggle()` "reverses"
+ if ( toggle ) {
+ dataShow.hidden = !hidden;
+ }
+
+ // Show elements before animating them
+ if ( hidden ) {
+ showHide( [ elem ], true );
+ }
+
+ /* eslint-disable no-loop-func */
+
+ anim.done( function() {
+
+ /* eslint-enable no-loop-func */
+
+ // The final step of a "hide" animation is actually hiding the element
+ if ( !hidden ) {
+ showHide( [ elem ] );
+ }
+ dataPriv.remove( elem, "fxshow" );
+ for ( prop in orig ) {
+ jQuery.style( elem, prop, orig[ prop ] );
+ }
+ } );
}
- // If this is a noop like .hide().hide(), restore an overwritten display value
- } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
- style.display = display;
+ // Per-property setup
+ propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+ if ( !( prop in dataShow ) ) {
+ dataShow[ prop ] = propTween.start;
+ if ( hidden ) {
+ propTween.end = propTween.start;
+ propTween.start = 0;
+ }
+ }
}
}
@@ -7265,8 +6880,8 @@ function propFilter( props, specialEasing ) {
value = hooks.expand( value );
delete props[ name ];
- // not quite $.extend, this wont overwrite keys already present.
- // also - reusing 'index' from above because we have the correct "name"
+ // Not quite $.extend, this won't overwrite existing keys.
+ // Reusing 'index' because we have the correct "name"
for ( index in value ) {
if ( !( index in props ) ) {
props[ index ] = value[ index ];
@@ -7283,28 +6898,31 @@ function Animation( elem, properties, options ) {
var result,
stopped,
index = 0,
- length = animationPrefilters.length,
+ length = Animation.prefilters.length,
deferred = jQuery.Deferred().always( function() {
- // don't match elem in the :animated selector
+
+ // Don't match elem in the :animated selector
delete tick.elem;
- }),
+ } ),
tick = function() {
if ( stopped ) {
return false;
}
var currentTime = fxNow || createFxNow(),
remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
- // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
+
+ // Support: Android 2.3 only
+ // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
temp = remaining / animation.duration || 0,
percent = 1 - temp,
index = 0,
length = animation.tweens.length;
- for ( ; index < length ; index++ ) {
+ for ( ; index < length; index++ ) {
animation.tweens[ index ].run( percent );
}
- deferred.notifyWith( elem, [ animation, percent, remaining ]);
+ deferred.notifyWith( elem, [ animation, percent, remaining ] );
if ( percent < 1 && length ) {
return remaining;
@@ -7313,10 +6931,13 @@ function Animation( elem, properties, options ) {
return false;
}
},
- animation = deferred.promise({
+ animation = deferred.promise( {
elem: elem,
props: jQuery.extend( {}, properties ),
- opts: jQuery.extend( true, { specialEasing: {} }, options ),
+ opts: jQuery.extend( true, {
+ specialEasing: {},
+ easing: jQuery.easing._default
+ }, options ),
originalProperties: properties,
originalOptions: options,
startTime: fxNow || createFxNow(),
@@ -7330,34 +6951,39 @@ function Animation( elem, properties, options ) {
},
stop: function( gotoEnd ) {
var index = 0,
- // if we are going to the end, we want to run all the tweens
+
+ // If we are going to the end, we want to run all the tweens
// otherwise we skip this part
length = gotoEnd ? animation.tweens.length : 0;
if ( stopped ) {
return this;
}
stopped = true;
- for ( ; index < length ; index++ ) {
+ for ( ; index < length; index++ ) {
animation.tweens[ index ].run( 1 );
}
- // resolve when we played the last frame
- // otherwise, reject
+ // Resolve when we played the last frame; otherwise, reject
if ( gotoEnd ) {
+ deferred.notifyWith( elem, [ animation, 1, 0 ] );
deferred.resolveWith( elem, [ animation, gotoEnd ] );
} else {
deferred.rejectWith( elem, [ animation, gotoEnd ] );
}
return this;
}
- }),
+ } ),
props = animation.props;
propFilter( props, animation.opts.specialEasing );
- for ( ; index < length ; index++ ) {
- result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+ for ( ; index < length; index++ ) {
+ result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
if ( result ) {
+ if ( jQuery.isFunction( result.stop ) ) {
+ jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
+ jQuery.proxy( result.stop, result );
+ }
return result;
}
}
@@ -7373,7 +6999,7 @@ function Animation( elem, properties, options ) {
elem: elem,
anim: animation,
queue: animation.opts.queue
- })
+ } )
);
// attach callbacks from options
@@ -7384,33 +7010,44 @@ function Animation( elem, properties, options ) {
}
jQuery.Animation = jQuery.extend( Animation, {
+
+ tweeners: {
+ "*": [ function( prop, value ) {
+ var tween = this.createTween( prop, value );
+ adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
+ return tween;
+ } ]
+ },
+
tweener: function( props, callback ) {
if ( jQuery.isFunction( props ) ) {
callback = props;
props = [ "*" ];
} else {
- props = props.split(" ");
+ props = props.match( rnotwhite );
}
var prop,
index = 0,
length = props.length;
- for ( ; index < length ; index++ ) {
+ for ( ; index < length; index++ ) {
prop = props[ index ];
- tweeners[ prop ] = tweeners[ prop ] || [];
- tweeners[ prop ].unshift( callback );
+ Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
+ Animation.tweeners[ prop ].unshift( callback );
}
},
+ prefilters: [ defaultPrefilter ],
+
prefilter: function( callback, prepend ) {
if ( prepend ) {
- animationPrefilters.unshift( callback );
+ Animation.prefilters.unshift( callback );
} else {
- animationPrefilters.push( callback );
+ Animation.prefilters.push( callback );
}
}
-});
+} );
jQuery.speed = function( speed, easing, fn ) {
var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
@@ -7420,10 +7057,17 @@ jQuery.speed = function( speed, easing, fn ) {
easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
};
- opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
- opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+ // Go to the end state if fx are off or if document is hidden
+ if ( jQuery.fx.off || document.hidden ) {
+ opt.duration = 0;
- // normalize opt.queue - true/undefined/null -> "fx"
+ } else {
+ opt.duration = typeof opt.duration === "number" ?
+ opt.duration : opt.duration in jQuery.fx.speeds ?
+ jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+ }
+
+ // Normalize opt.queue - true/undefined/null -> "fx"
if ( opt.queue == null || opt.queue === true ) {
opt.queue = "fx";
}
@@ -7444,24 +7088,25 @@ jQuery.speed = function( speed, easing, fn ) {
return opt;
};
-jQuery.fn.extend({
+jQuery.fn.extend( {
fadeTo: function( speed, to, easing, callback ) {
- // show any hidden elements after setting opacity to 0
- return this.filter( isHidden ).css( "opacity", 0 ).show()
+ // Show any hidden elements after setting opacity to 0
+ return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
- // animate to the value specified
- .end().animate({ opacity: to }, speed, easing, callback );
+ // Animate to the value specified
+ .end().animate( { opacity: to }, speed, easing, callback );
},
animate: function( prop, speed, easing, callback ) {
var empty = jQuery.isEmptyObject( prop ),
optall = jQuery.speed( speed, easing, callback ),
doAnimation = function() {
+
// Operate on a copy of prop so per-property easing won't be lost
var anim = Animation( this, jQuery.extend( {}, prop ), optall );
// Empty animations, or finishing resolves immediately
- if ( empty || jQuery._data( this, "finish" ) ) {
+ if ( empty || dataPriv.get( this, "finish" ) ) {
anim.stop( true );
}
};
@@ -7487,11 +7132,11 @@ jQuery.fn.extend({
this.queue( type || "fx", [] );
}
- return this.each(function() {
+ return this.each( function() {
var dequeue = true,
index = type != null && type + "queueHooks",
timers = jQuery.timers,
- data = jQuery._data( this );
+ data = dataPriv.get( this );
if ( index ) {
if ( data[ index ] && data[ index ].stop ) {
@@ -7506,44 +7151,46 @@ jQuery.fn.extend({
}
for ( index = timers.length; index--; ) {
- if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+ if ( timers[ index ].elem === this &&
+ ( type == null || timers[ index ].queue === type ) ) {
+
timers[ index ].anim.stop( gotoEnd );
dequeue = false;
timers.splice( index, 1 );
}
}
- // start the next in the queue if the last step wasn't forced
- // timers currently will call their complete callbacks, which will dequeue
- // but only if they were gotoEnd
+ // Start the next in the queue if the last step wasn't forced.
+ // Timers currently will call their complete callbacks, which
+ // will dequeue but only if they were gotoEnd.
if ( dequeue || !gotoEnd ) {
jQuery.dequeue( this, type );
}
- });
+ } );
},
finish: function( type ) {
if ( type !== false ) {
type = type || "fx";
}
- return this.each(function() {
+ return this.each( function() {
var index,
- data = jQuery._data( this ),
+ data = dataPriv.get( this ),
queue = data[ type + "queue" ],
hooks = data[ type + "queueHooks" ],
timers = jQuery.timers,
length = queue ? queue.length : 0;
- // enable finishing flag on private data
+ // Enable finishing flag on private data
data.finish = true;
- // empty the queue first
+ // Empty the queue first
jQuery.queue( this, type, [] );
if ( hooks && hooks.stop ) {
hooks.stop.call( this, true );
}
- // look for any active animations, and finish them
+ // Look for any active animations, and finish them
for ( index = timers.length; index--; ) {
if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
timers[ index ].anim.stop( true );
@@ -7551,33 +7198,33 @@ jQuery.fn.extend({
}
}
- // look for any animations in the old queue and finish them
+ // Look for any animations in the old queue and finish them
for ( index = 0; index < length; index++ ) {
if ( queue[ index ] && queue[ index ].finish ) {
queue[ index ].finish.call( this );
}
}
- // turn off finishing flag
+ // Turn off finishing flag
delete data.finish;
- });
+ } );
}
-});
+} );
-jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
var cssFn = jQuery.fn[ name ];
jQuery.fn[ name ] = function( speed, easing, callback ) {
return speed == null || typeof speed === "boolean" ?
cssFn.apply( this, arguments ) :
this.animate( genFx( name, true ), speed, easing, callback );
};
-});
+} );
// Generate shortcuts for custom animations
-jQuery.each({
- slideDown: genFx("show"),
- slideUp: genFx("hide"),
- slideToggle: genFx("toggle"),
+jQuery.each( {
+ slideDown: genFx( "show" ),
+ slideUp: genFx( "hide" ),
+ slideToggle: genFx( "toggle" ),
fadeIn: { opacity: "show" },
fadeOut: { opacity: "hide" },
fadeToggle: { opacity: "toggle" }
@@ -7585,18 +7232,19 @@ jQuery.each({
jQuery.fn[ name ] = function( speed, easing, callback ) {
return this.animate( props, speed, easing, callback );
};
-});
+} );
jQuery.timers = [];
jQuery.fx.tick = function() {
var timer,
- timers = jQuery.timers,
- i = 0;
+ i = 0,
+ timers = jQuery.timers;
fxNow = jQuery.now();
for ( ; i < timers.length; i++ ) {
timer = timers[ i ];
+
// Checks the timer has not already been removed
if ( !timer() && timers[ i ] === timer ) {
timers.splice( i--, 1 );
@@ -7619,375 +7267,139 @@ jQuery.fx.timer = function( timer ) {
};
jQuery.fx.interval = 13;
-
jQuery.fx.start = function() {
if ( !timerId ) {
- timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+ timerId = window.requestAnimationFrame ?
+ window.requestAnimationFrame( raf ) :
+ window.setInterval( jQuery.fx.tick, jQuery.fx.interval );
}
};
jQuery.fx.stop = function() {
- clearInterval( timerId );
+ if ( window.cancelAnimationFrame ) {
+ window.cancelAnimationFrame( timerId );
+ } else {
+ window.clearInterval( timerId );
+ }
+
timerId = null;
};
jQuery.fx.speeds = {
slow: 600,
fast: 200,
+
// Default speed
_default: 400
};
// Based off of the plugin by Clint Helfers, with permission.
-// http://blindsignals.com/index.php/2009/07/jquery-delay/
+// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
jQuery.fn.delay = function( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
type = type || "fx";
return this.queue( type, function( next, hooks ) {
- var timeout = setTimeout( next, time );
+ var timeout = window.setTimeout( next, time );
hooks.stop = function() {
- clearTimeout( timeout );
+ window.clearTimeout( timeout );
};
- });
+ } );
};
-(function() {
- // Minified: var a,b,c,d,e
- var input, div, select, a, opt;
-
- // Setup
- div = document.createElement( "div" );
- div.setAttribute( "className", "t" );
- div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
- a = div.getElementsByTagName("a")[ 0 ];
-
- // First batch of tests.
- select = document.createElement("select");
- opt = select.appendChild( document.createElement("option") );
- input = div.getElementsByTagName("input")[ 0 ];
-
- a.style.cssText = "top:1px";
-
- // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
- support.getSetAttribute = div.className !== "t";
-
- // Get the style information from getAttribute
- // (IE uses .cssText instead)
- support.style = /top/.test( a.getAttribute("style") );
+( function() {
+ var input = document.createElement( "input" ),
+ select = document.createElement( "select" ),
+ opt = select.appendChild( document.createElement( "option" ) );
- // Make sure that URLs aren't manipulated
- // (IE normalizes it by default)
- support.hrefNormalized = a.getAttribute("href") === "/a";
+ input.type = "checkbox";
- // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
- support.checkOn = !!input.value;
+ // Support: Android <=4.3 only
+ // Default value for a checkbox should be "on"
+ support.checkOn = input.value !== "";
- // Make sure that a selected-by-default option has a working selected property.
- // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ // Support: IE <=11 only
+ // Must access selectedIndex to make default options select
support.optSelected = opt.selected;
- // Tests for enctype support on a form (#6743)
- support.enctype = !!document.createElement("form").enctype;
-
- // Make sure that the options inside disabled selects aren't marked as disabled
- // (WebKit marks them as disabled)
- select.disabled = true;
- support.optDisabled = !opt.disabled;
-
- // Support: IE8 only
- // Check if we can trust getAttribute("value")
+ // Support: IE <=11 only
+ // An input loses its value after becoming a radio
input = document.createElement( "input" );
- input.setAttribute( "value", "" );
- support.input = input.getAttribute( "value" ) === "";
-
- // Check if an input maintains its value after becoming a radio
input.value = "t";
- input.setAttribute( "type", "radio" );
+ input.type = "radio";
support.radioValue = input.value === "t";
-})();
-
+} )();
-var rreturn = /\r/g;
-jQuery.fn.extend({
- val: function( value ) {
- var hooks, ret, isFunction,
- elem = this[0];
+var boolHook,
+ attrHandle = jQuery.expr.attrHandle;
- if ( !arguments.length ) {
- if ( elem ) {
- hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
-
- if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
- return ret;
- }
-
- ret = elem.value;
-
- return typeof ret === "string" ?
- // handle most common string cases
- ret.replace(rreturn, "") :
- // handle cases where value is null/undef or number
- ret == null ? "" : ret;
- }
-
- return;
- }
-
- isFunction = jQuery.isFunction( value );
-
- return this.each(function( i ) {
- var val;
-
- if ( this.nodeType !== 1 ) {
- return;
- }
-
- if ( isFunction ) {
- val = value.call( this, i, jQuery( this ).val() );
- } else {
- val = value;
- }
-
- // Treat null/undefined as ""; convert numbers to string
- if ( val == null ) {
- val = "";
- } else if ( typeof val === "number" ) {
- val += "";
- } else if ( jQuery.isArray( val ) ) {
- val = jQuery.map( val, function( value ) {
- return value == null ? "" : value + "";
- });
- }
-
- hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
-
- // If set returns undefined, fall back to normal setting
- if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
- this.value = val;
- }
- });
- }
-});
-
-jQuery.extend({
- valHooks: {
- option: {
- get: function( elem ) {
- var val = jQuery.find.attr( elem, "value" );
- return val != null ?
- val :
- // Support: IE10-11+
- // option.text throws exceptions (#14686, #14858)
- jQuery.trim( jQuery.text( elem ) );
- }
- },
- select: {
- get: function( elem ) {
- var value, option,
- options = elem.options,
- index = elem.selectedIndex,
- one = elem.type === "select-one" || index < 0,
- values = one ? null : [],
- max = one ? index + 1 : options.length,
- i = index < 0 ?
- max :
- one ? index : 0;
-
- // Loop through all the selected options
- for ( ; i < max; i++ ) {
- option = options[ i ];
-
- // oldIE doesn't update selected after form reset (#2551)
- if ( ( option.selected || i === index ) &&
- // Don't return options that are disabled or in a disabled optgroup
- ( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
- ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
-
- // Get the specific value for the option
- value = jQuery( option ).val();
-
- // We don't need an array for one selects
- if ( one ) {
- return value;
- }
-
- // Multi-Selects return an array
- values.push( value );
- }
- }
-
- return values;
- },
-
- set: function( elem, value ) {
- var optionSet, option,
- options = elem.options,
- values = jQuery.makeArray( value ),
- i = options.length;
-
- while ( i-- ) {
- option = options[ i ];
-
- if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {
-
- // Support: IE6
- // When new option element is added to select box we need to
- // force reflow of newly added node in order to workaround delay
- // of initialization properties
- try {
- option.selected = optionSet = true;
-
- } catch ( _ ) {
-
- // Will be executed only in IE6
- option.scrollHeight;
- }
-
- } else {
- option.selected = false;
- }
- }
-
- // Force browsers to behave consistently when non-matching value is set
- if ( !optionSet ) {
- elem.selectedIndex = -1;
- }
-
- return options;
- }
- }
- }
-});
-
-// Radios and checkboxes getter/setter
-jQuery.each([ "radio", "checkbox" ], function() {
- jQuery.valHooks[ this ] = {
- set: function( elem, value ) {
- if ( jQuery.isArray( value ) ) {
- return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
- }
- }
- };
- if ( !support.checkOn ) {
- jQuery.valHooks[ this ].get = function( elem ) {
- // Support: Webkit
- // "" is returned instead of "on" if a value isn't specified
- return elem.getAttribute("value") === null ? "on" : elem.value;
- };
- }
-});
-
-
-
-
-var nodeHook, boolHook,
- attrHandle = jQuery.expr.attrHandle,
- ruseDefault = /^(?:checked|selected)$/i,
- getSetAttribute = support.getSetAttribute,
- getSetInput = support.input;
-
-jQuery.fn.extend({
+jQuery.fn.extend( {
attr: function( name, value ) {
return access( this, jQuery.attr, name, value, arguments.length > 1 );
},
removeAttr: function( name ) {
- return this.each(function() {
+ return this.each( function() {
jQuery.removeAttr( this, name );
- });
+ } );
}
-});
+} );
-jQuery.extend({
+jQuery.extend( {
attr: function( elem, name, value ) {
- var hooks, ret,
+ var ret, hooks,
nType = elem.nodeType;
- // don't get/set attributes on text, comment and attribute nodes
- if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ // Don't get/set attributes on text, comment and attribute nodes
+ if ( nType === 3 || nType === 8 || nType === 2 ) {
return;
}
// Fallback to prop when attributes are not supported
- if ( typeof elem.getAttribute === strundefined ) {
+ if ( typeof elem.getAttribute === "undefined" ) {
return jQuery.prop( elem, name, value );
}
- // All attributes are lowercase
+ // Attribute hooks are determined by the lowercase version
// Grab necessary hook if one is defined
if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
- name = name.toLowerCase();
- hooks = jQuery.attrHooks[ name ] ||
- ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
+ hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
+ ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
}
if ( value !== undefined ) {
-
if ( value === null ) {
jQuery.removeAttr( elem, name );
+ return;
+ }
- } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ if ( hooks && "set" in hooks &&
+ ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
return ret;
-
- } else {
- elem.setAttribute( name, value + "" );
- return value;
}
- } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
- return ret;
-
- } else {
- ret = jQuery.find.attr( elem, name );
-
- // Non-existent attributes return null, we normalize to undefined
- return ret == null ?
- undefined :
- ret;
+ elem.setAttribute( name, value + "" );
+ return value;
}
- },
-
- removeAttr: function( elem, value ) {
- var name, propName,
- i = 0,
- attrNames = value && value.match( rnotwhite );
- if ( attrNames && elem.nodeType === 1 ) {
- while ( (name = attrNames[i++]) ) {
- propName = jQuery.propFix[ name ] || name;
-
- // Boolean attributes get special treatment (#10870)
- if ( jQuery.expr.match.bool.test( name ) ) {
- // Set corresponding property to false
- if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
- elem[ propName ] = false;
- // Support: IE<9
- // Also clear defaultChecked/defaultSelected (if appropriate)
- } else {
- elem[ jQuery.camelCase( "default-" + name ) ] =
- elem[ propName ] = false;
- }
+ if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
+ return ret;
+ }
- // See #9699 for explanation of this approach (setting first, then removal)
- } else {
- jQuery.attr( elem, name, "" );
- }
+ ret = jQuery.find.attr( elem, name );
- elem.removeAttribute( getSetAttribute ? name : propName );
- }
- }
+ // Non-existent attributes return null, we normalize to undefined
+ return ret == null ? undefined : ret;
},
attrHooks: {
type: {
set: function( elem, value ) {
- if ( !support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
- // Setting the type on a radio button after the value resets the value in IE6-9
- // Reset value to default in case type is set after value during creation
+ if ( !support.radioValue && value === "radio" &&
+ jQuery.nodeName( elem, "input" ) ) {
var val = elem.value;
elem.setAttribute( "type", value );
if ( val ) {
@@ -7997,264 +7409,163 @@ jQuery.extend({
}
}
}
+ },
+
+ removeAttr: function( elem, value ) {
+ var name,
+ i = 0,
+ attrNames = value && value.match( rnotwhite );
+
+ if ( attrNames && elem.nodeType === 1 ) {
+ while ( ( name = attrNames[ i++ ] ) ) {
+ elem.removeAttribute( name );
+ }
+ }
}
-});
+} );
-// Hook for boolean attributes
+// Hooks for boolean attributes
boolHook = {
set: function( elem, value, name ) {
if ( value === false ) {
+
// Remove boolean attributes when set to false
jQuery.removeAttr( elem, name );
- } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
- // IE<8 needs the *property* name
- elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
-
- // Use defaultChecked and defaultSelected for oldIE
} else {
- elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
+ elem.setAttribute( name, name );
}
-
return name;
}
};
-// Retrieve booleans specially
jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
-
var getter = attrHandle[ name ] || jQuery.find.attr;
- attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
- function( elem, name, isXML ) {
- var ret, handle;
- if ( !isXML ) {
- // Avoid an infinite loop by temporarily removing this function from the getter
- handle = attrHandle[ name ];
- attrHandle[ name ] = ret;
- ret = getter( elem, name, isXML ) != null ?
- name.toLowerCase() :
- null;
- attrHandle[ name ] = handle;
- }
- return ret;
- } :
- function( elem, name, isXML ) {
- if ( !isXML ) {
- return elem[ jQuery.camelCase( "default-" + name ) ] ?
- name.toLowerCase() :
- null;
- }
- };
-});
-
-// fix oldIE attroperties
-if ( !getSetInput || !getSetAttribute ) {
- jQuery.attrHooks.value = {
- set: function( elem, value, name ) {
- if ( jQuery.nodeName( elem, "input" ) ) {
- // Does not return so that setAttribute is also used
- elem.defaultValue = value;
- } else {
- // Use nodeHook if defined (#1954); otherwise setAttribute is fine
- return nodeHook && nodeHook.set( elem, value, name );
- }
- }
- };
-}
-
-// IE6/7 do not support getting/setting some attributes with get/setAttribute
-if ( !getSetAttribute ) {
-
- // Use this for any attribute in IE6/7
- // This fixes almost every IE6/7 issue
- nodeHook = {
- set: function( elem, value, name ) {
- // Set the existing or create a new attribute node
- var ret = elem.getAttributeNode( name );
- if ( !ret ) {
- elem.setAttributeNode(
- (ret = elem.ownerDocument.createAttribute( name ))
- );
- }
-
- ret.value = value += "";
-
- // Break association with cloned elements by also using setAttribute (#9646)
- if ( name === "value" || value === elem.getAttribute( name ) ) {
- return value;
- }
- }
- };
-
- // Some attributes are constructed with empty-string values when not defined
- attrHandle.id = attrHandle.name = attrHandle.coords =
- function( elem, name, isXML ) {
- var ret;
- if ( !isXML ) {
- return (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
- ret.value :
- null;
- }
- };
-
- // Fixing value retrieval on a button requires this module
- jQuery.valHooks.button = {
- get: function( elem, name ) {
- var ret = elem.getAttributeNode( name );
- if ( ret && ret.specified ) {
- return ret.value;
- }
- },
- set: nodeHook.set
- };
-
- // Set contenteditable to false on removals(#10429)
- // Setting to empty string throws an error as an invalid value
- jQuery.attrHooks.contenteditable = {
- set: function( elem, value, name ) {
- nodeHook.set( elem, value === "" ? false : value, name );
- }
- };
+ attrHandle[ name ] = function( elem, name, isXML ) {
+ var ret, handle,
+ lowercaseName = name.toLowerCase();
- // Set width and height to auto instead of 0 on empty string( Bug #8150 )
- // This is for removals
- jQuery.each([ "width", "height" ], function( i, name ) {
- jQuery.attrHooks[ name ] = {
- set: function( elem, value ) {
- if ( value === "" ) {
- elem.setAttribute( name, "auto" );
- return value;
- }
- }
- };
- });
-}
+ if ( !isXML ) {
-if ( !support.style ) {
- jQuery.attrHooks.style = {
- get: function( elem ) {
- // Return undefined in the case of empty string
- // Note: IE uppercases css property names, but if we were to .toLowerCase()
- // .cssText, that would destroy case senstitivity in URL's, like in "background"
- return elem.style.cssText || undefined;
- },
- set: function( elem, value ) {
- return ( elem.style.cssText = value + "" );
+ // Avoid an infinite loop by temporarily removing this function from the getter
+ handle = attrHandle[ lowercaseName ];
+ attrHandle[ lowercaseName ] = ret;
+ ret = getter( elem, name, isXML ) != null ?
+ lowercaseName :
+ null;
+ attrHandle[ lowercaseName ] = handle;
}
+ return ret;
};
-}
+} );
-var rfocusable = /^(?:input|select|textarea|button|object)$/i,
+var rfocusable = /^(?:input|select|textarea|button)$/i,
rclickable = /^(?:a|area)$/i;
-jQuery.fn.extend({
+jQuery.fn.extend( {
prop: function( name, value ) {
return access( this, jQuery.prop, name, value, arguments.length > 1 );
},
removeProp: function( name ) {
- name = jQuery.propFix[ name ] || name;
- return this.each(function() {
- // try/catch handles cases where IE balks (such as removing a property on window)
- try {
- this[ name ] = undefined;
- delete this[ name ];
- } catch( e ) {}
- });
+ return this.each( function() {
+ delete this[ jQuery.propFix[ name ] || name ];
+ } );
}
-});
-
-jQuery.extend({
- propFix: {
- "for": "htmlFor",
- "class": "className"
- },
+} );
+jQuery.extend( {
prop: function( elem, name, value ) {
- var ret, hooks, notxml,
+ var ret, hooks,
nType = elem.nodeType;
- // don't get/set properties on text, comment and attribute nodes
- if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ // Don't get/set properties on text, comment and attribute nodes
+ if ( nType === 3 || nType === 8 || nType === 2 ) {
return;
}
- notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+ if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
- if ( notxml ) {
// Fix name and attach hooks
name = jQuery.propFix[ name ] || name;
hooks = jQuery.propHooks[ name ];
}
if ( value !== undefined ) {
- return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
- ret :
- ( elem[ name ] = value );
+ if ( hooks && "set" in hooks &&
+ ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
+ return ret;
+ }
- } else {
- return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
- ret :
- elem[ name ];
+ return ( elem[ name ] = value );
}
+
+ if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
+ return ret;
+ }
+
+ return elem[ name ];
},
propHooks: {
tabIndex: {
get: function( elem ) {
- // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
- // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+
+ // Support: IE <=9 - 11 only
+ // elem.tabIndex doesn't always return the
+ // correct value when it hasn't been explicitly set
+ // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
// Use proper attribute retrieval(#12072)
var tabindex = jQuery.find.attr( elem, "tabindex" );
return tabindex ?
parseInt( tabindex, 10 ) :
- rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
- 0 :
- -1;
+ rfocusable.test( elem.nodeName ) ||
+ rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ -1;
}
}
- }
-});
+ },
-// Some attributes require a special call on IE
-// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
-if ( !support.hrefNormalized ) {
- // href/src property should get the full normalized URL (#10299/#12915)
- jQuery.each([ "href", "src" ], function( i, name ) {
- jQuery.propHooks[ name ] = {
- get: function( elem ) {
- return elem.getAttribute( name, 4 );
- }
- };
- });
-}
+ propFix: {
+ "for": "htmlFor",
+ "class": "className"
+ }
+} );
-// Support: Safari, IE9+
-// mis-reports the default selected property of an option
-// Accessing the parent's selectedIndex property fixes it
+// Support: IE <=11 only
+// Accessing the selectedIndex property
+// forces the browser to respect setting selected
+// on the option
+// The getter ensures a default option is selected
+// when in an optgroup
if ( !support.optSelected ) {
jQuery.propHooks.selected = {
get: function( elem ) {
var parent = elem.parentNode;
-
+ if ( parent && parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ return null;
+ },
+ set: function( elem ) {
+ var parent = elem.parentNode;
if ( parent ) {
parent.selectedIndex;
- // Make sure that it also works with optgroups, see #5701
if ( parent.parentNode ) {
parent.parentNode.selectedIndex;
}
}
- return null;
}
};
}
-jQuery.each([
+jQuery.each( [
"tabIndex",
"readOnly",
"maxLength",
@@ -8267,54 +7578,48 @@ jQuery.each([
"contentEditable"
], function() {
jQuery.propFix[ this.toLowerCase() ] = this;
-});
-
-// IE6/7 call enctype encoding
-if ( !support.enctype ) {
- jQuery.propFix.enctype = "encoding";
-}
+} );
var rclass = /[\t\r\n\f]/g;
-jQuery.fn.extend({
+function getClass( elem ) {
+ return elem.getAttribute && elem.getAttribute( "class" ) || "";
+}
+
+jQuery.fn.extend( {
addClass: function( value ) {
- var classes, elem, cur, clazz, j, finalValue,
- i = 0,
- len = this.length,
- proceed = typeof value === "string" && value;
+ var classes, elem, cur, curValue, clazz, j, finalValue,
+ i = 0;
if ( jQuery.isFunction( value ) ) {
- return this.each(function( j ) {
- jQuery( this ).addClass( value.call( this, j, this.className ) );
- });
+ return this.each( function( j ) {
+ jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
+ } );
}
- if ( proceed ) {
- // The disjunction here is for better compressibility (see removeClass)
- classes = ( value || "" ).match( rnotwhite ) || [];
+ if ( typeof value === "string" && value ) {
+ classes = value.match( rnotwhite ) || [];
- for ( ; i < len; i++ ) {
- elem = this[ i ];
- cur = elem.nodeType === 1 && ( elem.className ?
- ( " " + elem.className + " " ).replace( rclass, " " ) :
- " "
- );
+ while ( ( elem = this[ i++ ] ) ) {
+ curValue = getClass( elem );
+ cur = elem.nodeType === 1 &&
+ ( " " + curValue + " " ).replace( rclass, " " );
if ( cur ) {
j = 0;
- while ( (clazz = classes[j++]) ) {
+ while ( ( clazz = classes[ j++ ] ) ) {
if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
cur += clazz + " ";
}
}
- // only assign if different to avoid unneeded rendering.
+ // Only assign if different to avoid unneeded rendering.
finalValue = jQuery.trim( cur );
- if ( elem.className !== finalValue ) {
- elem.className = finalValue;
+ if ( curValue !== finalValue ) {
+ elem.setAttribute( "class", finalValue );
}
}
}
@@ -8324,40 +7629,43 @@ jQuery.fn.extend({
},
removeClass: function( value ) {
- var classes, elem, cur, clazz, j, finalValue,
- i = 0,
- len = this.length,
- proceed = arguments.length === 0 || typeof value === "string" && value;
+ var classes, elem, cur, curValue, clazz, j, finalValue,
+ i = 0;
if ( jQuery.isFunction( value ) ) {
- return this.each(function( j ) {
- jQuery( this ).removeClass( value.call( this, j, this.className ) );
- });
+ return this.each( function( j ) {
+ jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
+ } );
}
- if ( proceed ) {
- classes = ( value || "" ).match( rnotwhite ) || [];
- for ( ; i < len; i++ ) {
- elem = this[ i ];
+ if ( !arguments.length ) {
+ return this.attr( "class", "" );
+ }
+
+ if ( typeof value === "string" && value ) {
+ classes = value.match( rnotwhite ) || [];
+
+ while ( ( elem = this[ i++ ] ) ) {
+ curValue = getClass( elem );
+
// This expression is here for better compressibility (see addClass)
- cur = elem.nodeType === 1 && ( elem.className ?
- ( " " + elem.className + " " ).replace( rclass, " " ) :
- ""
- );
+ cur = elem.nodeType === 1 &&
+ ( " " + curValue + " " ).replace( rclass, " " );
if ( cur ) {
j = 0;
- while ( (clazz = classes[j++]) ) {
+ while ( ( clazz = classes[ j++ ] ) ) {
+
// Remove *all* instances
- while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
+ while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
cur = cur.replace( " " + clazz + " ", " " );
}
}
- // only assign if different to avoid unneeded rendering.
- finalValue = value ? jQuery.trim( cur ) : "";
- if ( elem.className !== finalValue ) {
- elem.className = finalValue;
+ // Only assign if different to avoid unneeded rendering.
+ finalValue = jQuery.trim( cur );
+ if ( curValue !== finalValue ) {
+ elem.setAttribute( "class", finalValue );
}
}
}
@@ -8374,21 +7682,27 @@ jQuery.fn.extend({
}
if ( jQuery.isFunction( value ) ) {
- return this.each(function( i ) {
- jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
- });
+ return this.each( function( i ) {
+ jQuery( this ).toggleClass(
+ value.call( this, i, getClass( this ), stateVal ),
+ stateVal
+ );
+ } );
}
- return this.each(function() {
+ return this.each( function() {
+ var className, i, self, classNames;
+
if ( type === "string" ) {
- // toggle individual class names
- var className,
- i = 0,
- self = jQuery( this ),
- classNames = value.match( rnotwhite ) || [];
-
- while ( (className = classNames[ i++ ]) ) {
- // check each className given, space separated list
+
+ // Toggle individual class names
+ i = 0;
+ self = jQuery( this );
+ classNames = value.match( rnotwhite ) || [];
+
+ while ( ( className = classNames[ i++ ] ) ) {
+
+ // Check each className given, space separated list
if ( self.hasClass( className ) ) {
self.removeClass( className );
} else {
@@ -8397,34 +7711,224 @@ jQuery.fn.extend({
}
// Toggle whole class name
- } else if ( type === strundefined || type === "boolean" ) {
- if ( this.className ) {
- // store className if set
- jQuery._data( this, "__className__", this.className );
+ } else if ( value === undefined || type === "boolean" ) {
+ className = getClass( this );
+ if ( className ) {
+
+ // Store className if set
+ dataPriv.set( this, "__className__", className );
}
- // If the element has a class name or if we're passed "false",
+ // If the element has a class name or if we're passed `false`,
// then remove the whole classname (if there was one, the above saved it).
// Otherwise bring back whatever was previously saved (if anything),
// falling back to the empty string if nothing was stored.
- this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+ if ( this.setAttribute ) {
+ this.setAttribute( "class",
+ className || value === false ?
+ "" :
+ dataPriv.get( this, "__className__" ) || ""
+ );
+ }
}
- });
+ } );
},
hasClass: function( selector ) {
- var className = " " + selector + " ",
- i = 0,
- l = this.length;
- for ( ; i < l; i++ ) {
- if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+ var className, elem,
+ i = 0;
+
+ className = " " + selector + " ";
+ while ( ( elem = this[ i++ ] ) ) {
+ if ( elem.nodeType === 1 &&
+ ( " " + getClass( elem ) + " " ).replace( rclass, " " )
+ .indexOf( className ) > -1
+ ) {
return true;
}
}
return false;
}
-});
+} );
+
+
+
+
+var rreturn = /\r/g,
+ rspaces = /[\x20\t\r\n\f]+/g;
+
+jQuery.fn.extend( {
+ val: function( value ) {
+ var hooks, ret, isFunction,
+ elem = this[ 0 ];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.type ] ||
+ jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+ if ( hooks &&
+ "get" in hooks &&
+ ( ret = hooks.get( elem, "value" ) ) !== undefined
+ ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+
+ // Handle most common string cases
+ ret.replace( rreturn, "" ) :
+
+ // Handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each( function( i ) {
+ var val;
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, jQuery( this ).val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+
+ } else if ( typeof val === "number" ) {
+ val += "";
+
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map( val, function( value ) {
+ return value == null ? "" : value + "";
+ } );
+ }
+
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ } );
+ }
+} );
+
+jQuery.extend( {
+ valHooks: {
+ option: {
+ get: function( elem ) {
+
+ var val = jQuery.find.attr( elem, "value" );
+ return val != null ?
+ val :
+
+ // Support: IE <=10 - 11 only
+ // option.text throws exceptions (#14686, #14858)
+ // Strip and collapse whitespace
+ // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
+ jQuery.trim( jQuery.text( elem ) ).replace( rspaces, " " );
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, option,
+ options = elem.options,
+ index = elem.selectedIndex,
+ one = elem.type === "select-one",
+ values = one ? null : [],
+ max = one ? index + 1 : options.length,
+ i = index < 0 ?
+ max :
+ one ? index : 0;
+
+ // Loop through all the selected options
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // Support: IE <=9 only
+ // IE8-9 doesn't update selected after form reset (#2551)
+ if ( ( option.selected || i === index ) &&
+
+ // Don't return options that are disabled or in a disabled optgroup
+ !option.disabled &&
+ ( !option.parentNode.disabled ||
+ !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var optionSet, option,
+ options = elem.options,
+ values = jQuery.makeArray( value ),
+ i = options.length;
+
+ while ( i-- ) {
+ option = options[ i ];
+
+ /* eslint-disable no-cond-assign */
+
+ if ( option.selected =
+ jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
+ ) {
+ optionSet = true;
+ }
+
+ /* eslint-enable no-cond-assign */
+ }
+
+ // Force browsers to behave consistently when non-matching value is set
+ if ( !optionSet ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ }
+} );
+
+// Radios and checkboxes getter/setter
+jQuery.each( [ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
+ }
+ }
+ };
+ if ( !support.checkOn ) {
+ jQuery.valHooks[ this ].get = function( elem ) {
+ return elem.getAttribute( "value" ) === null ? "on" : elem.value;
+ };
+ }
+} );
@@ -8432,9 +7936,182 @@ jQuery.fn.extend({
// Return jQuery for attributes-only inclusion
-jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;
+
+jQuery.extend( jQuery.event, {
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+
+ var i, cur, tmp, bubbleType, ontype, handle, special,
+ eventPath = [ elem || document ],
+ type = hasOwn.call( event, "type" ) ? event.type : event,
+ namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
+
+ cur = tmp = elem = elem || document;
+
+ // Don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf( "." ) > -1 ) {
+
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split( "." );
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+ ontype = type.indexOf( ":" ) < 0 && "on" + type;
+
+ // Caller can pass in a jQuery.Event object, Object, or just an event type string
+ event = event[ jQuery.expando ] ?
+ event :
+ new jQuery.Event( type, typeof event === "object" && event );
+
+ // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+ event.isTrigger = onlyHandlers ? 2 : 3;
+ event.namespace = namespaces.join( "." );
+ event.rnamespace = event.namespace ?
+ new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
+ null;
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data == null ?
+ [ event ] :
+ jQuery.makeArray( data, [ event ] );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ if ( !rfocusMorph.test( bubbleType + type ) ) {
+ cur = cur.parentNode;
+ }
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push( cur );
+ tmp = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( tmp === ( elem.ownerDocument || document ) ) {
+ eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+ }
+ }
+
+ // Fire handlers on the event path
+ i = 0;
+ while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
+
+ event.type = i > 1 ?
+ bubbleType :
+ special.bindType || type;
+
+ // jQuery handler
+ handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
+ dataPriv.get( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+
+ // Native handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && handle.apply && acceptData( cur ) ) {
+ event.result = handle.apply( cur, data );
+ if ( event.result === false ) {
+ event.preventDefault();
+ }
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( ( !special._default ||
+ special._default.apply( eventPath.pop(), data ) === false ) &&
+ acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name as the event.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ tmp = elem[ ontype ];
+
+ if ( tmp ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ elem[ type ]();
+ jQuery.event.triggered = undefined;
+
+ if ( tmp ) {
+ elem[ ontype ] = tmp;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ // Piggyback on a donor event to simulate a different one
+ // Used only for `focus(in | out)` events
+ simulate: function( type, elem, event ) {
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ {
+ type: type,
+ isSimulated: true
+ }
+ );
+
+ jQuery.event.trigger( e, null, elem );
+ }
+
+} );
+
+jQuery.fn.extend( {
+
+ trigger: function( type, data ) {
+ return this.each( function() {
+ jQuery.event.trigger( type, data, this );
+ } );
+ },
+ triggerHandler: function( type, data ) {
+ var elem = this[ 0 ];
+ if ( elem ) {
+ return jQuery.event.trigger( type, data, elem, true );
+ }
+ }
+} );
+
+
+jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
- "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+ "change select submit keydown keypress keyup contextmenu" ).split( " " ),
+ function( i, name ) {
// Handle event binding
jQuery.fn[ name ] = function( data, fn ) {
@@ -8442,100 +8119,85 @@ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblcl
this.on( name, null, data, fn ) :
this.trigger( name );
};
-});
+} );
-jQuery.fn.extend({
+jQuery.fn.extend( {
hover: function( fnOver, fnOut ) {
return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
- },
-
- bind: function( types, data, fn ) {
- return this.on( types, null, data, fn );
- },
- unbind: function( types, fn ) {
- return this.off( types, null, fn );
- },
-
- delegate: function( selector, types, data, fn ) {
- return this.on( types, selector, data, fn );
- },
- undelegate: function( selector, types, fn ) {
- // ( namespace ) or ( selector, types [, fn] )
- return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
}
-});
+} );
-var nonce = jQuery.now();
-var rquery = (/\?/);
+support.focusin = "onfocusin" in window;
-var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;
+// Support: Firefox <=44
+// Firefox doesn't have focus(in | out) events
+// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
+//
+// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
+// focus(in | out) events fire after focus & blur events,
+// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
+// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
+if ( !support.focusin ) {
+ jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
-jQuery.parseJSON = function( data ) {
- // Attempt to parse using the native JSON parser first
- if ( window.JSON && window.JSON.parse ) {
- // Support: Android 2.3
- // Workaround failure to string-cast null input
- return window.JSON.parse( data + "" );
- }
+ // Attach a single capturing handler on the document while someone wants focusin/focusout
+ var handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
+ };
- var requireNonComma,
- depth = null,
- str = jQuery.trim( data + "" );
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ var doc = this.ownerDocument || this,
+ attaches = dataPriv.access( doc, fix );
- // Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
- // after removing valid tokens
- return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {
+ if ( !attaches ) {
+ doc.addEventListener( orig, handler, true );
+ }
+ dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
+ },
+ teardown: function() {
+ var doc = this.ownerDocument || this,
+ attaches = dataPriv.access( doc, fix ) - 1;
- // Force termination if we see a misplaced comma
- if ( requireNonComma && comma ) {
- depth = 0;
- }
+ if ( !attaches ) {
+ doc.removeEventListener( orig, handler, true );
+ dataPriv.remove( doc, fix );
- // Perform no more replacements after returning to outermost depth
- if ( depth === 0 ) {
- return token;
- }
+ } else {
+ dataPriv.access( doc, fix, attaches );
+ }
+ }
+ };
+ } );
+}
+var location = window.location;
- // Commas must not follow "[", "{", or ","
- requireNonComma = open || comma;
+var nonce = jQuery.now();
- // Determine new depth
- // array/object open ("[" or "{"): depth += true - false (increment)
- // array/object close ("]" or "}"): depth += false - true (decrement)
- // other cases ("," or primitive): depth += true - true (numeric cast)
- depth += !close - !open;
+var rquery = ( /\?/ );
- // Remove this token
- return "";
- }) ) ?
- ( Function( "return " + str ) )() :
- jQuery.error( "Invalid JSON: " + data );
-};
// Cross-browser xml parsing
jQuery.parseXML = function( data ) {
- var xml, tmp;
+ var xml;
if ( !data || typeof data !== "string" ) {
return null;
}
+
+ // Support: IE 9 - 11 only
+ // IE throws on parseFromString with invalid input.
try {
- if ( window.DOMParser ) { // Standard
- tmp = new DOMParser();
- xml = tmp.parseFromString( data, "text/xml" );
- } else { // IE
- xml = new ActiveXObject( "Microsoft.XMLDOM" );
- xml.async = "false";
- xml.loadXML( data );
- }
- } catch( e ) {
+ xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
+ } catch ( e ) {
xml = undefined;
}
- if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+
+ if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
jQuery.error( "Invalid XML: " + data );
}
return xml;
@@ -8543,18 +8205,130 @@ jQuery.parseXML = function( data ) {
var
- // Document location
- ajaxLocParts,
- ajaxLocation,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+function buildParams( prefix, obj, traditional, add ) {
+ var name;
+
+ if ( jQuery.isArray( obj ) ) {
+
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+
+ // Item is non-scalar (array or object), encode its numeric index.
+ buildParams(
+ prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
+ v,
+ traditional,
+ add
+ );
+ }
+ } );
+
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+
+ // Serialize object item.
+ for ( name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+
+// Serialize an array of form elements or a set of
+// key/values into a query string
+jQuery.param = function( a, traditional ) {
+ var prefix,
+ s = [],
+ add = function( key, valueOrFunction ) {
+
+ // If value is a function, invoke it and use its return value
+ var value = jQuery.isFunction( valueOrFunction ) ?
+ valueOrFunction() :
+ valueOrFunction;
+
+ s[ s.length ] = encodeURIComponent( key ) + "=" +
+ encodeURIComponent( value == null ? "" : value );
+ };
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ } );
+
+ } else {
+
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" );
+};
+
+jQuery.fn.extend( {
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+ serializeArray: function() {
+ return this.map( function() {
+
+ // Can add propHook for "elements" to filter or add form elements
+ var elements = jQuery.prop( this, "elements" );
+ return elements ? jQuery.makeArray( elements ) : this;
+ } )
+ .filter( function() {
+ var type = this.type;
+
+ // Use .is( ":disabled" ) so that fieldset[disabled] works
+ return this.name && !jQuery( this ).is( ":disabled" ) &&
+ rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+ ( this.checked || !rcheckableType.test( type ) );
+ } )
+ .map( function( i, elem ) {
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val ) {
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ } ) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ } ).get();
+ }
+} );
+
+var
+ r20 = /%20/g,
rhash = /#.*$/,
rts = /([?&])_=[^&]*/,
- rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
+
// #7653, #8125, #8152: local protocol detection
rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
rnoContent = /^(?:GET|HEAD)$/,
rprotocol = /^\/\//,
- rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
/* Prefilters
* 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
@@ -8575,22 +8349,11 @@ var
transports = {},
// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
- allTypes = "*/".concat("*");
+ allTypes = "*/".concat( "*" ),
-// #8138, IE may throw an exception when accessing
-// a field from window.location if document.domain has been set
-try {
- ajaxLocation = location.href;
-} catch( e ) {
- // Use the href attribute of an A element
- // since IE will modify it given document.location
- ajaxLocation = document.createElement( "a" );
- ajaxLocation.href = "";
- ajaxLocation = ajaxLocation.href;
-}
-
-// Segment location into parts
-ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+ // Anchor tag for parsing the document origin
+ originAnchor = document.createElement( "a" );
+ originAnchor.href = location.href;
// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
function addToPrefiltersOrTransports( structure ) {
@@ -8608,16 +8371,18 @@ function addToPrefiltersOrTransports( structure ) {
dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
if ( jQuery.isFunction( func ) ) {
+
// For each dataType in the dataTypeExpression
- while ( (dataType = dataTypes[i++]) ) {
+ while ( ( dataType = dataTypes[ i++ ] ) ) {
+
// Prepend if requested
- if ( dataType.charAt( 0 ) === "+" ) {
+ if ( dataType[ 0 ] === "+" ) {
dataType = dataType.slice( 1 ) || "*";
- (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
+ ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
// Otherwise append
} else {
- (structure[ dataType ] = structure[ dataType ] || []).push( func );
+ ( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
}
}
}
@@ -8635,14 +8400,16 @@ function inspectPrefiltersOrTransports( structure, options, originalOptions, jqX
inspected[ dataType ] = true;
jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
- if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+ if ( typeof dataTypeOrTransport === "string" &&
+ !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+
options.dataTypes.unshift( dataTypeOrTransport );
inspect( dataTypeOrTransport );
return false;
} else if ( seekingTransport ) {
return !( selected = dataTypeOrTransport );
}
- });
+ } );
return selected;
}
@@ -8653,12 +8420,12 @@ function inspectPrefiltersOrTransports( structure, options, originalOptions, jqX
// that takes "flat" options (not to be deep extended)
// Fixes #9887
function ajaxExtend( target, src ) {
- var deep, key,
+ var key, deep,
flatOptions = jQuery.ajaxSettings.flatOptions || {};
for ( key in src ) {
if ( src[ key ] !== undefined ) {
- ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
+ ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
}
}
if ( deep ) {
@@ -8673,7 +8440,8 @@ function ajaxExtend( target, src ) {
* - returns the corresponding response
*/
function ajaxHandleResponses( s, jqXHR, responses ) {
- var firstDataType, ct, finalDataType, type,
+
+ var ct, type, finalDataType, firstDataType,
contents = s.contents,
dataTypes = s.dataTypes;
@@ -8681,7 +8449,7 @@ function ajaxHandleResponses( s, jqXHR, responses ) {
while ( dataTypes[ 0 ] === "*" ) {
dataTypes.shift();
if ( ct === undefined ) {
- ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
+ ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
}
}
@@ -8699,9 +8467,10 @@ function ajaxHandleResponses( s, jqXHR, responses ) {
if ( dataTypes[ 0 ] in responses ) {
finalDataType = dataTypes[ 0 ];
} else {
+
// Try convertible dataTypes
for ( type in responses ) {
- if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
finalDataType = type;
break;
}
@@ -8709,6 +8478,7 @@ function ajaxHandleResponses( s, jqXHR, responses ) {
firstDataType = type;
}
}
+
// Or just use first one
finalDataType = finalDataType || firstDataType;
}
@@ -8730,6 +8500,7 @@ function ajaxHandleResponses( s, jqXHR, responses ) {
function ajaxConvert( s, response, jqXHR, isSuccess ) {
var conv2, current, conv, tmp, prev,
converters = {},
+
// Work with a copy of dataTypes in case we need to modify it for conversion
dataTypes = s.dataTypes.slice();
@@ -8782,6 +8553,7 @@ function ajaxConvert( s, response, jqXHR, isSuccess ) {
conv = converters[ prev + " " + tmp[ 0 ] ] ||
converters[ "* " + tmp[ 0 ] ];
if ( conv ) {
+
// Condense equivalence converters
if ( conv === true ) {
conv = converters[ conv2 ];
@@ -8801,13 +8573,16 @@ function ajaxConvert( s, response, jqXHR, isSuccess ) {
if ( conv !== true ) {
// Unless errors are allowed to bubble, catch and return them
- if ( conv && s[ "throws" ] ) {
+ if ( conv && s.throws ) {
response = conv( response );
} else {
try {
response = conv( response );
} catch ( e ) {
- return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+ return {
+ state: "parsererror",
+ error: conv ? e : "No conversion from " + prev + " to " + current
+ };
}
}
}
@@ -8818,7 +8593,7 @@ function ajaxConvert( s, response, jqXHR, isSuccess ) {
return { state: "success", data: response };
}
-jQuery.extend({
+jQuery.extend( {
// Counter for holding the number of active queries
active: 0,
@@ -8828,13 +8603,14 @@ jQuery.extend({
etag: {},
ajaxSettings: {
- url: ajaxLocation,
+ url: location.href,
type: "GET",
- isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+ isLocal: rlocalProtocol.test( location.protocol ),
global: true,
processData: true,
async: true,
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+
/*
timeout: 0,
data: null,
@@ -8856,9 +8632,9 @@ jQuery.extend({
},
contents: {
- xml: /xml/,
- html: /html/,
- json: /json/
+ xml: /\bxml\b/,
+ html: /\bhtml/,
+ json: /\bjson\b/
},
responseFields: {
@@ -8878,7 +8654,7 @@ jQuery.extend({
"text html": true,
// Evaluate text as a json expression
- "text json": jQuery.parseJSON,
+ "text json": JSON.parse,
// Parse text as xml
"text xml": jQuery.parseXML
@@ -8922,43 +8698,59 @@ jQuery.extend({
// Force options to be an object
options = options || {};
- var // Cross-domain detection vars
- parts,
- // Loop variable
- i,
+ var transport,
+
// URL without anti-cache param
cacheURL,
- // Response headers as string
+
+ // Response headers
responseHeadersString,
+ responseHeaders,
+
// timeout handle
timeoutTimer,
+ // Url cleanup var
+ urlAnchor,
+
+ // Request state (becomes false upon send and true upon completion)
+ completed,
+
// To know if global events are to be dispatched
fireGlobals,
- transport,
- // Response headers
- responseHeaders,
+ // Loop variable
+ i,
+
+ // uncached part of the url
+ uncached,
+
// Create the final options object
s = jQuery.ajaxSetup( {}, options ),
+
// Callbacks context
callbackContext = s.context || s,
+
// Context for global events is callbackContext if it is a DOM node or jQuery collection
- globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
- jQuery( callbackContext ) :
- jQuery.event,
+ globalEventContext = s.context &&
+ ( callbackContext.nodeType || callbackContext.jquery ) ?
+ jQuery( callbackContext ) :
+ jQuery.event,
+
// Deferreds
deferred = jQuery.Deferred(),
- completeDeferred = jQuery.Callbacks("once memory"),
+ completeDeferred = jQuery.Callbacks( "once memory" ),
+
// Status-dependent callbacks
statusCode = s.statusCode || {},
+
// Headers (they are sent all at once)
requestHeaders = {},
requestHeadersNames = {},
- // The jqXHR state
- state = 0,
+
// Default abort message
strAbort = "canceled",
+
// Fake xhr
jqXHR = {
readyState: 0,
@@ -8966,11 +8758,11 @@ jQuery.extend({
// Builds headers hashtable if needed
getResponseHeader: function( key ) {
var match;
- if ( state === 2 ) {
+ if ( completed ) {
if ( !responseHeaders ) {
responseHeaders = {};
- while ( (match = rheaders.exec( responseHeadersString )) ) {
- responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+ while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
+ responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
}
}
match = responseHeaders[ key.toLowerCase() ];
@@ -8980,14 +8772,14 @@ jQuery.extend({
// Raw string
getAllResponseHeaders: function() {
- return state === 2 ? responseHeadersString : null;
+ return completed ? responseHeadersString : null;
},
// Caches the header
setRequestHeader: function( name, value ) {
- var lname = name.toLowerCase();
- if ( !state ) {
- name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+ if ( completed == null ) {
+ name = requestHeadersNames[ name.toLowerCase() ] =
+ requestHeadersNames[ name.toLowerCase() ] || name;
requestHeaders[ name ] = value;
}
return this;
@@ -8995,7 +8787,7 @@ jQuery.extend({
// Overrides response content-type header
overrideMimeType: function( type ) {
- if ( !state ) {
+ if ( completed == null ) {
s.mimeType = type;
}
return this;
@@ -9005,14 +8797,16 @@ jQuery.extend({
statusCode: function( map ) {
var code;
if ( map ) {
- if ( state < 2 ) {
+ if ( completed ) {
+
+ // Execute the appropriate callbacks
+ jqXHR.always( map[ jqXHR.status ] );
+ } else {
+
+ // Lazy-add the new callbacks in a way that preserves old ones
for ( code in map ) {
- // Lazy-add the new callback in a way that preserves old ones
statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
}
- } else {
- // Execute the appropriate callbacks
- jqXHR.always( map[ jqXHR.status ] );
}
}
return this;
@@ -9030,30 +8824,41 @@ jQuery.extend({
};
// Attach deferreds
- deferred.promise( jqXHR ).complete = completeDeferred.add;
- jqXHR.success = jqXHR.done;
- jqXHR.error = jqXHR.fail;
+ deferred.promise( jqXHR );
- // Remove hash character (#7531: and string promotion)
- // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+ // Add protocol if not provided (prefilters might expect it)
// Handle falsy url in the settings object (#10093: consistency with old signature)
// We also use the url parameter if available
- s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+ s.url = ( ( url || s.url || location.href ) + "" )
+ .replace( rprotocol, location.protocol + "//" );
// Alias method option to type as per ticket #12004
s.type = options.method || options.type || s.method || s.type;
// Extract dataTypes list
- s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
+ s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
- // A cross-domain request is in order when we have a protocol:host:port mismatch
+ // A cross-domain request is in order when the origin doesn't match the current origin.
if ( s.crossDomain == null ) {
- parts = rurl.exec( s.url.toLowerCase() );
- s.crossDomain = !!( parts &&
- ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
- ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
- ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
- );
+ urlAnchor = document.createElement( "a" );
+
+ // Support: IE <=8 - 11, Edge 12 - 13
+ // IE throws exception on accessing the href property if url is malformed,
+ // e.g. http://example.com:80x/
+ try {
+ urlAnchor.href = s.url;
+
+ // Support: IE <=8 - 11 only
+ // Anchor's host property isn't correctly set when s.url is relative
+ urlAnchor.href = urlAnchor.href;
+ s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
+ urlAnchor.protocol + "//" + urlAnchor.host;
+ } catch ( e ) {
+
+ // If there is an error parsing the URL, assume it is crossDomain,
+ // it can be rejected by the transport if it is invalid
+ s.crossDomain = true;
+ }
}
// Convert data if not already a string
@@ -9065,16 +8870,17 @@ jQuery.extend({
inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
// If request was aborted inside a prefilter, stop there
- if ( state === 2 ) {
+ if ( completed ) {
return jqXHR;
}
// We can fire global events as of now if asked to
- fireGlobals = s.global;
+ // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
+ fireGlobals = jQuery.event && s.global;
// Watch for a new set of requests
if ( fireGlobals && jQuery.active++ === 0 ) {
- jQuery.event.trigger("ajaxStart");
+ jQuery.event.trigger( "ajaxStart" );
}
// Uppercase the type
@@ -9085,28 +8891,36 @@ jQuery.extend({
// Save the URL in case we're toying with the If-Modified-Since
// and/or If-None-Match header later on
- cacheURL = s.url;
+ // Remove hash to simplify url manipulation
+ cacheURL = s.url.replace( rhash, "" );
// More options handling for requests with no content
if ( !s.hasContent ) {
+ // Remember the hash so we can put it back
+ uncached = s.url.slice( cacheURL.length );
+
// If data is available, append data to url
if ( s.data ) {
- cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+ cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
+
// #9682: remove data so that it's not used in an eventual retry
delete s.data;
}
- // Add anti-cache in url if needed
+ // Add anti-cache in uncached url if needed
if ( s.cache === false ) {
- s.url = rts.test( cacheURL ) ?
+ cacheURL = cacheURL.replace( rts, "" );
+ uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached;
+ }
- // If there is already a '_' parameter, set its value
- cacheURL.replace( rts, "$1_=" + nonce++ ) :
+ // Put hash and anti-cache on the URL that will be requested (gh-1732)
+ s.url = cacheURL + uncached;
- // Otherwise add one to the end
- cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
- }
+ // Change '%20' to '+' if this is encoded form body content (gh-2658)
+ } else if ( s.data && s.processData &&
+ ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
+ s.data = s.data.replace( r20, "+" );
}
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
@@ -9127,8 +8941,9 @@ jQuery.extend({
// Set the Accepts header for the server, depending on the dataType
jqXHR.setRequestHeader(
"Accept",
- s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
- s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
+ s.accepts[ s.dataTypes[ 0 ] ] +
+ ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
s.accepts[ "*" ]
);
@@ -9138,18 +8953,20 @@ jQuery.extend({
}
// Allow custom headers/mimetypes and early abort
- if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+ if ( s.beforeSend &&
+ ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
+
// Abort if not done already and return
return jqXHR.abort();
}
- // aborting is no longer a cancellation
+ // Aborting is no longer a cancellation
strAbort = "abort";
// Install callbacks on deferreds
- for ( i in { success: 1, error: 1, complete: 1 } ) {
- jqXHR[ i ]( s[ i ] );
- }
+ completeDeferred.add( s.complete );
+ jqXHR.done( s.success );
+ jqXHR.fail( s.error );
// Get transport
transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
@@ -9164,24 +8981,31 @@ jQuery.extend({
if ( fireGlobals ) {
globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
}
+
+ // If request was aborted inside ajaxSend, stop there
+ if ( completed ) {
+ return jqXHR;
+ }
+
// Timeout
if ( s.async && s.timeout > 0 ) {
- timeoutTimer = setTimeout(function() {
- jqXHR.abort("timeout");
+ timeoutTimer = window.setTimeout( function() {
+ jqXHR.abort( "timeout" );
}, s.timeout );
}
try {
- state = 1;
+ completed = false;
transport.send( requestHeaders, done );
} catch ( e ) {
- // Propagate exception as error if not done
- if ( state < 2 ) {
- done( -1, e );
- // Simply rethrow otherwise
- } else {
+
+ // Rethrow post-completion exceptions
+ if ( completed ) {
throw e;
}
+
+ // Propagate others as results
+ done( -1, e );
}
}
@@ -9190,17 +9014,16 @@ jQuery.extend({
var isSuccess, success, error, response, modified,
statusText = nativeStatusText;
- // Called once
- if ( state === 2 ) {
+ // Ignore repeat invocations
+ if ( completed ) {
return;
}
- // State is "done" now
- state = 2;
+ completed = true;
// Clear timeout if it exists
if ( timeoutTimer ) {
- clearTimeout( timeoutTimer );
+ window.clearTimeout( timeoutTimer );
}
// Dereference transport for early garbage collection
@@ -9229,11 +9052,11 @@ jQuery.extend({
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
if ( s.ifModified ) {
- modified = jqXHR.getResponseHeader("Last-Modified");
+ modified = jqXHR.getResponseHeader( "Last-Modified" );
if ( modified ) {
jQuery.lastModified[ cacheURL ] = modified;
}
- modified = jqXHR.getResponseHeader("etag");
+ modified = jqXHR.getResponseHeader( "etag" );
if ( modified ) {
jQuery.etag[ cacheURL ] = modified;
}
@@ -9255,8 +9078,8 @@ jQuery.extend({
isSuccess = !error;
}
} else {
- // We extract error from statusText
- // then normalize statusText and status for non-aborts
+
+ // Extract error from statusText and normalize for non-aborts
error = statusText;
if ( status || !statusText ) {
statusText = "error";
@@ -9291,9 +9114,10 @@ jQuery.extend({
if ( fireGlobals ) {
globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+
// Handle the global AJAX counter
if ( !( --jQuery.active ) ) {
- jQuery.event.trigger("ajaxStop");
+ jQuery.event.trigger( "ajaxStop" );
}
}
}
@@ -9308,72 +9132,70 @@ jQuery.extend({
getScript: function( url, callback ) {
return jQuery.get( url, undefined, callback, "script" );
}
-});
+} );
jQuery.each( [ "get", "post" ], function( i, method ) {
jQuery[ method ] = function( url, data, callback, type ) {
- // shift arguments if data argument was omitted
+
+ // Shift arguments if data argument was omitted
if ( jQuery.isFunction( data ) ) {
type = type || callback;
callback = data;
data = undefined;
}
- return jQuery.ajax({
+ // The url can be an options object (which then must have .url)
+ return jQuery.ajax( jQuery.extend( {
url: url,
type: method,
dataType: type,
data: data,
success: callback
- });
+ }, jQuery.isPlainObject( url ) && url ) );
};
-});
-
-// Attach a bunch of functions for handling common AJAX events
-jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
- jQuery.fn[ type ] = function( fn ) {
- return this.on( type, fn );
- };
-});
+} );
jQuery._evalUrl = function( url ) {
- return jQuery.ajax({
+ return jQuery.ajax( {
url: url,
+
+ // Make this explicit, since user can override this through ajaxSetup (#11264)
type: "GET",
dataType: "script",
+ cache: true,
async: false,
global: false,
"throws": true
- });
+ } );
};
-jQuery.fn.extend({
+jQuery.fn.extend( {
wrapAll: function( html ) {
- if ( jQuery.isFunction( html ) ) {
- return this.each(function(i) {
- jQuery(this).wrapAll( html.call(this, i) );
- });
- }
+ var wrap;
+
+ if ( this[ 0 ] ) {
+ if ( jQuery.isFunction( html ) ) {
+ html = html.call( this[ 0 ] );
+ }
- if ( this[0] ) {
// The elements to wrap the target around
- var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+ wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
- if ( this[0].parentNode ) {
- wrap.insertBefore( this[0] );
+ if ( this[ 0 ].parentNode ) {
+ wrap.insertBefore( this[ 0 ] );
}
- wrap.map(function() {
+ wrap.map( function() {
var elem = this;
- while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
- elem = elem.firstChild;
+ while ( elem.firstElementChild ) {
+ elem = elem.firstElementChild;
}
return elem;
- }).append( this );
+ } ).append( this );
}
return this;
@@ -9381,12 +9203,12 @@ jQuery.fn.extend({
wrapInner: function( html ) {
if ( jQuery.isFunction( html ) ) {
- return this.each(function(i) {
- jQuery(this).wrapInner( html.call(this, i) );
- });
+ return this.each( function( i ) {
+ jQuery( this ).wrapInner( html.call( this, i ) );
+ } );
}
- return this.each(function() {
+ return this.each( function() {
var self = jQuery( this ),
contents = self.contents();
@@ -9396,342 +9218,214 @@ jQuery.fn.extend({
} else {
self.append( html );
}
- });
+ } );
},
wrap: function( html ) {
var isFunction = jQuery.isFunction( html );
- return this.each(function(i) {
- jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
- });
+ return this.each( function( i ) {
+ jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );
+ } );
},
- unwrap: function() {
- return this.parent().each(function() {
- if ( !jQuery.nodeName( this, "body" ) ) {
- jQuery( this ).replaceWith( this.childNodes );
- }
- }).end();
+ unwrap: function( selector ) {
+ this.parent( selector ).not( "body" ).each( function() {
+ jQuery( this ).replaceWith( this.childNodes );
+ } );
+ return this;
}
-});
+} );
-jQuery.expr.filters.hidden = function( elem ) {
- // Support: Opera <= 12.12
- // Opera reports offsetWidths and offsetHeights less than zero on some elements
- return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
- (!support.reliableHiddenOffsets() &&
- ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+jQuery.expr.pseudos.hidden = function( elem ) {
+ return !jQuery.expr.pseudos.visible( elem );
};
-
-jQuery.expr.filters.visible = function( elem ) {
- return !jQuery.expr.filters.hidden( elem );
+jQuery.expr.pseudos.visible = function( elem ) {
+ return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
};
-var r20 = /%20/g,
- rbracket = /\[\]$/,
- rCRLF = /\r?\n/g,
- rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
- rsubmittable = /^(?:input|select|textarea|keygen)/i;
-
-function buildParams( prefix, obj, traditional, add ) {
- var name;
-
- if ( jQuery.isArray( obj ) ) {
- // Serialize array item.
- jQuery.each( obj, function( i, v ) {
- if ( traditional || rbracket.test( prefix ) ) {
- // Treat each array item as a scalar.
- add( prefix, v );
-
- } else {
- // Item is non-scalar (array or object), encode its numeric index.
- buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
- }
- });
-
- } else if ( !traditional && jQuery.type( obj ) === "object" ) {
- // Serialize object item.
- for ( name in obj ) {
- buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
- }
-
- } else {
- // Serialize scalar item.
- add( prefix, obj );
- }
-}
-
-// Serialize an array of form elements or a set of
-// key/values into a query string
-jQuery.param = function( a, traditional ) {
- var prefix,
- s = [],
- add = function( key, value ) {
- // If value is a function, invoke it and return its value
- value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
- s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
- };
-
- // Set traditional to true for jQuery <= 1.3.2 behavior.
- if ( traditional === undefined ) {
- traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
- }
-
- // If an array was passed in, assume that it is an array of form elements.
- if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
- // Serialize the form elements
- jQuery.each( a, function() {
- add( this.name, this.value );
- });
-
- } else {
- // If traditional, encode the "old" way (the way 1.3.2 or older
- // did it), otherwise encode params recursively.
- for ( prefix in a ) {
- buildParams( prefix, a[ prefix ], traditional, add );
- }
- }
-
- // Return the resulting serialization
- return s.join( "&" ).replace( r20, "+" );
+jQuery.ajaxSettings.xhr = function() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch ( e ) {}
};
-jQuery.fn.extend({
- serialize: function() {
- return jQuery.param( this.serializeArray() );
- },
- serializeArray: function() {
- return this.map(function() {
- // Can add propHook for "elements" to filter or add form elements
- var elements = jQuery.prop( this, "elements" );
- return elements ? jQuery.makeArray( elements ) : this;
- })
- .filter(function() {
- var type = this.type;
- // Use .is(":disabled") so that fieldset[disabled] works
- return this.name && !jQuery( this ).is( ":disabled" ) &&
- rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
- ( this.checked || !rcheckableType.test( type ) );
- })
- .map(function( i, elem ) {
- var val = jQuery( this ).val();
-
- return val == null ?
- null :
- jQuery.isArray( val ) ?
- jQuery.map( val, function( val ) {
- return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
- }) :
- { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
- }).get();
- }
-});
-
-
-// Create the request object
-// (This is still attached to ajaxSettings for backward compatibility)
-jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
- // Support: IE6+
- function() {
+var xhrSuccessStatus = {
- // XHR cannot access local files, always use ActiveX for that case
- return !this.isLocal &&
+ // File protocol always yields status code 0, assume 200
+ 0: 200,
- // Support: IE7-8
- // oldIE XHR does not support non-RFC2616 methods (#13240)
- // See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
- // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
- // Although this check for six methods instead of eight
- // since IE also does not support "trace" and "connect"
- /^(get|post|head|put|delete|options)$/i.test( this.type ) &&
-
- createStandardXHR() || createActiveXHR();
- } :
- // For all other browsers, use the standard XMLHttpRequest object
- createStandardXHR;
-
-var xhrId = 0,
- xhrCallbacks = {},
+ // Support: IE <=9 only
+ // #1450: sometimes IE returns 1223 when it should be 204
+ 1223: 204
+ },
xhrSupported = jQuery.ajaxSettings.xhr();
-// Support: IE<10
-// Open requests must be manually aborted on unload (#5280)
-if ( window.ActiveXObject ) {
- jQuery( window ).on( "unload", function() {
- for ( var key in xhrCallbacks ) {
- xhrCallbacks[ key ]( undefined, true );
- }
- });
-}
-
-// Determine support properties
support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
-xhrSupported = support.ajax = !!xhrSupported;
+support.ajax = xhrSupported = !!xhrSupported;
-// Create transport if the browser can provide an xhr
-if ( xhrSupported ) {
+jQuery.ajaxTransport( function( options ) {
+ var callback, errorCallback;
- jQuery.ajaxTransport(function( options ) {
- // Cross domain only allowed if supported through XMLHttpRequest
- if ( !options.crossDomain || support.cors ) {
-
- var callback;
-
- return {
- send: function( headers, complete ) {
- var i,
- xhr = options.xhr(),
- id = ++xhrId;
-
- // Open the socket
- xhr.open( options.type, options.url, options.async, options.username, options.password );
-
- // Apply custom fields if provided
- if ( options.xhrFields ) {
- for ( i in options.xhrFields ) {
- xhr[ i ] = options.xhrFields[ i ];
- }
- }
-
- // Override mime type if needed
- if ( options.mimeType && xhr.overrideMimeType ) {
- xhr.overrideMimeType( options.mimeType );
- }
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( support.cors || xhrSupported && !options.crossDomain ) {
+ return {
+ send: function( headers, complete ) {
+ var i,
+ xhr = options.xhr();
+
+ xhr.open(
+ options.type,
+ options.url,
+ options.async,
+ options.username,
+ options.password
+ );
- // X-Requested-With header
- // For cross-domain requests, seeing as conditions for a preflight are
- // akin to a jigsaw puzzle, we simply never set it to be sure.
- // (it can always be set on a per-request basis or even using ajaxSetup)
- // For same-domain requests, won't change header if already provided.
- if ( !options.crossDomain && !headers["X-Requested-With"] ) {
- headers["X-Requested-With"] = "XMLHttpRequest";
+ // Apply custom fields if provided
+ if ( options.xhrFields ) {
+ for ( i in options.xhrFields ) {
+ xhr[ i ] = options.xhrFields[ i ];
}
+ }
- // Set headers
- for ( i in headers ) {
- // Support: IE<9
- // IE's ActiveXObject throws a 'Type Mismatch' exception when setting
- // request header to a null-value.
- //
- // To keep consistent with other XHR implementations, cast the value
- // to string and ignore `undefined`.
- if ( headers[ i ] !== undefined ) {
- xhr.setRequestHeader( i, headers[ i ] + "" );
- }
- }
+ // Override mime type if needed
+ if ( options.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( options.mimeType );
+ }
- // Do send the request
- // This may raise an exception which is actually
- // handled in jQuery.ajax (so no try/catch here)
- xhr.send( ( options.hasContent && options.data ) || null );
-
- // Listener
- callback = function( _, isAbort ) {
- var status, statusText, responses;
-
- // Was never called and is aborted or complete
- if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
- // Clean up
- delete xhrCallbacks[ id ];
- callback = undefined;
- xhr.onreadystatechange = jQuery.noop;
-
- // Abort manually if needed
- if ( isAbort ) {
- if ( xhr.readyState !== 4 ) {
- xhr.abort();
- }
- } else {
- responses = {};
- status = xhr.status;
-
- // Support: IE<10
- // Accessing binary-data responseText throws an exception
- // (#11426)
- if ( typeof xhr.responseText === "string" ) {
- responses.text = xhr.responseText;
- }
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
+ headers[ "X-Requested-With" ] = "XMLHttpRequest";
+ }
- // Firefox throws an exception when accessing
- // statusText for faulty cross-domain requests
- try {
- statusText = xhr.statusText;
- } catch( e ) {
- // We normalize with Webkit giving an empty statusText
- statusText = "";
- }
+ // Set headers
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
- // Filter status for non standard behaviors
+ // Callback
+ callback = function( type ) {
+ return function() {
+ if ( callback ) {
+ callback = errorCallback = xhr.onload =
+ xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
+
+ if ( type === "abort" ) {
+ xhr.abort();
+ } else if ( type === "error" ) {
+
+ // Support: IE <=9 only
+ // On a manual native abort, IE9 throws
+ // errors on any property access that is not readyState
+ if ( typeof xhr.status !== "number" ) {
+ complete( 0, "error" );
+ } else {
+ complete(
- // If the request is local and we have data: assume a success
- // (success with no data won't get notified, that's the best we
- // can do given current implementations)
- if ( !status && options.isLocal && !options.crossDomain ) {
- status = responses.text ? 200 : 404;
- // IE - #1450: sometimes returns 1223 when it should be 204
- } else if ( status === 1223 ) {
- status = 204;
+ // File: protocol always yields status 0; see #8605, #14207
+ xhr.status,
+ xhr.statusText
+ );
}
+ } else {
+ complete(
+ xhrSuccessStatus[ xhr.status ] || xhr.status,
+ xhr.statusText,
+
+ // Support: IE <=9 only
+ // IE9 has no XHR2 but throws on binary (trac-11426)
+ // For XHR2 non-text, let the caller handle it (gh-2498)
+ ( xhr.responseType || "text" ) !== "text" ||
+ typeof xhr.responseText !== "string" ?
+ { binary: xhr.response } :
+ { text: xhr.responseText },
+ xhr.getAllResponseHeaders()
+ );
}
}
+ };
+ };
+
+ // Listen to events
+ xhr.onload = callback();
+ errorCallback = xhr.onerror = callback( "error" );
- // Call complete if needed
- if ( responses ) {
- complete( status, statusText, responses, xhr.getAllResponseHeaders() );
+ // Support: IE 9 only
+ // Use onreadystatechange to replace onabort
+ // to handle uncaught aborts
+ if ( xhr.onabort !== undefined ) {
+ xhr.onabort = errorCallback;
+ } else {
+ xhr.onreadystatechange = function() {
+
+ // Check readyState before timeout as it changes
+ if ( xhr.readyState === 4 ) {
+
+ // Allow onerror to be called first,
+ // but that will not handle a native abort
+ // Also, save errorCallback to a variable
+ // as xhr.onerror cannot be accessed
+ window.setTimeout( function() {
+ if ( callback ) {
+ errorCallback();
+ }
+ } );
}
};
+ }
- if ( !options.async ) {
- // if we're in sync mode we fire the callback
- callback();
- } else if ( xhr.readyState === 4 ) {
- // (IE6 & IE7) if it's in cache and has been
- // retrieved directly we need to fire the callback
- setTimeout( callback );
- } else {
- // Add to the list of active xhr callbacks
- xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
- }
- },
+ // Create the abort callback
+ callback = callback( "abort" );
- abort: function() {
+ try {
+
+ // Do send the request (this may raise an exception)
+ xhr.send( options.hasContent && options.data || null );
+ } catch ( e ) {
+
+ // #14683: Only rethrow if this hasn't been notified as an error yet
if ( callback ) {
- callback( undefined, true );
+ throw e;
}
}
- };
- }
- });
-}
+ },
-// Functions to create xhrs
-function createStandardXHR() {
- try {
- return new window.XMLHttpRequest();
- } catch( e ) {}
-}
+ abort: function() {
+ if ( callback ) {
+ callback();
+ }
+ }
+ };
+ }
+} );
-function createActiveXHR() {
- try {
- return new window.ActiveXObject( "Microsoft.XMLHTTP" );
- } catch( e ) {}
-}
+// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
+jQuery.ajaxPrefilter( function( s ) {
+ if ( s.crossDomain ) {
+ s.contents.script = false;
+ }
+} );
// Install script dataType
-jQuery.ajaxSetup({
+jQuery.ajaxSetup( {
accepts: {
- script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+ script: "text/javascript, application/javascript, " +
+ "application/ecmascript, application/x-ecmascript"
},
contents: {
- script: /(?:java|ecma)script/
+ script: /\b(?:java|ecma)script\b/
},
converters: {
"text script": function( text ) {
@@ -9739,78 +9433,51 @@ jQuery.ajaxSetup({
return text;
}
}
-});
+} );
-// Handle cache's special case and global
+// Handle cache's special case and crossDomain
jQuery.ajaxPrefilter( "script", function( s ) {
if ( s.cache === undefined ) {
s.cache = false;
}
if ( s.crossDomain ) {
s.type = "GET";
- s.global = false;
}
-});
+} );
// Bind script tag hack transport
-jQuery.ajaxTransport( "script", function(s) {
+jQuery.ajaxTransport( "script", function( s ) {
// This transport only deals with cross domain requests
if ( s.crossDomain ) {
-
- var script,
- head = document.head || jQuery("head")[0] || document.documentElement;
-
+ var script, callback;
return {
-
- send: function( _, callback ) {
-
- script = document.createElement("script");
-
- script.async = true;
-
- if ( s.scriptCharset ) {
- script.charset = s.scriptCharset;
- }
-
- script.src = s.url;
-
- // Attach handlers for all browsers
- script.onload = script.onreadystatechange = function( _, isAbort ) {
-
- if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
-
- // Handle memory leak in IE
- script.onload = script.onreadystatechange = null;
-
- // Remove the script
- if ( script.parentNode ) {
- script.parentNode.removeChild( script );
- }
-
- // Dereference the script
- script = null;
-
- // Callback if not abort
- if ( !isAbort ) {
- callback( 200, "success" );
+ send: function( _, complete ) {
+ script = jQuery( "<script>" ).prop( {
+ charset: s.scriptCharset,
+ src: s.url
+ } ).on(
+ "load error",
+ callback = function( evt ) {
+ script.remove();
+ callback = null;
+ if ( evt ) {
+ complete( evt.type === "error" ? 404 : 200, evt.type );
}
}
- };
+ );
- // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
// Use native DOM manipulation to avoid our domManip AJAX trickery
- head.insertBefore( script, head.firstChild );
+ document.head.appendChild( script[ 0 ] );
},
-
abort: function() {
- if ( script ) {
- script.onload( undefined, true );
+ if ( callback ) {
+ callback();
}
}
};
}
-});
+} );
@@ -9819,14 +9486,14 @@ var oldCallbacks = [],
rjsonp = /(=)\?(?=&|$)|\?\?/;
// Default jsonp settings
-jQuery.ajaxSetup({
+jQuery.ajaxSetup( {
jsonp: "callback",
jsonpCallback: function() {
var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
this[ callback ] = true;
return callback;
}
-});
+} );
// Detect, normalize options and install callbacks for jsonp requests
jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
@@ -9834,7 +9501,10 @@ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
var callbackName, overwritten, responseContainer,
jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
"url" :
- typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
+ typeof s.data === "string" &&
+ ( s.contentType || "" )
+ .indexOf( "application/x-www-form-urlencoded" ) === 0 &&
+ rjsonp.test( s.data ) && "data"
);
// Handle iff the expected data type is "jsonp" or we have a parameter to set
@@ -9853,14 +9523,14 @@ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
}
// Use data converter to retrieve json after script execution
- s.converters["script json"] = function() {
+ s.converters[ "script json" ] = function() {
if ( !responseContainer ) {
jQuery.error( callbackName + " was not called" );
}
return responseContainer[ 0 ];
};
- // force json dataType
+ // Force json dataType
s.dataTypes[ 0 ] = "json";
// Install callback
@@ -9870,16 +9540,24 @@ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
};
// Clean-up function (fires after converters)
- jqXHR.always(function() {
- // Restore preexisting value
- window[ callbackName ] = overwritten;
+ jqXHR.always( function() {
+
+ // If previous value didn't exist - remove it
+ if ( overwritten === undefined ) {
+ jQuery( window ).removeProp( callbackName );
+
+ // Otherwise restore preexisting value
+ } else {
+ window[ callbackName ] = overwritten;
+ }
// Save back as free
if ( s[ callbackName ] ) {
- // make sure that re-using the options doesn't screw things around
+
+ // Make sure that re-using the options doesn't screw things around
s.jsonpCallback = originalSettings.jsonpCallback;
- // save the callback name for future use
+ // Save the callback name for future use
oldCallbacks.push( callbackName );
}
@@ -9889,38 +9567,70 @@ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
}
responseContainer = overwritten = undefined;
- });
+ } );
// Delegate to script
return "script";
}
-});
+} );
-// data: string of html
-// context (optional): If specified, the fragment will be created in this context, defaults to document
+// Support: Safari 8 only
+// In Safari 8 documents created via document.implementation.createHTMLDocument
+// collapse sibling forms: the second one becomes a child of the first one.
+// Because of that, this security measure has to be disabled in Safari 8.
+// https://bugs.webkit.org/show_bug.cgi?id=137337
+support.createHTMLDocument = ( function() {
+ var body = document.implementation.createHTMLDocument( "" ).body;
+ body.innerHTML = "<form></form><form></form>";
+ return body.childNodes.length === 2;
+} )();
+
+
+// Argument "data" should be string of html
+// context (optional): If specified, the fragment will be created in this context,
+// defaults to document
// keepScripts (optional): If true, will include scripts passed in the html string
jQuery.parseHTML = function( data, context, keepScripts ) {
- if ( !data || typeof data !== "string" ) {
- return null;
+ if ( typeof data !== "string" ) {
+ return [];
}
if ( typeof context === "boolean" ) {
keepScripts = context;
context = false;
}
- context = context || document;
- var parsed = rsingleTag.exec( data ),
- scripts = !keepScripts && [];
+ var base, parsed, scripts;
+
+ if ( !context ) {
+
+ // Stop scripts or inline event handlers from being executed immediately
+ // by using document.implementation
+ if ( support.createHTMLDocument ) {
+ context = document.implementation.createHTMLDocument( "" );
+
+ // Set the base href for the created document
+ // so any parsed elements with URLs
+ // are based on the document's URL (gh-2965)
+ base = context.createElement( "base" );
+ base.href = document.location.href;
+ context.head.appendChild( base );
+ } else {
+ context = document;
+ }
+ }
+
+ parsed = rsingleTag.exec( data );
+ scripts = !keepScripts && [];
// Single tag
if ( parsed ) {
- return [ context.createElement( parsed[1] ) ];
+ return [ context.createElement( parsed[ 1 ] ) ];
}
- parsed = jQuery.buildFragment( [ data ], context, scripts );
+ parsed = buildFragment( [ data ], context, scripts );
if ( scripts && scripts.length ) {
jQuery( scripts ).remove();
@@ -9930,23 +9640,16 @@ jQuery.parseHTML = function( data, context, keepScripts ) {
};
-// Keep a copy of the old load method
-var _load = jQuery.fn.load;
-
/**
* Load a url into a page
*/
jQuery.fn.load = function( url, params, callback ) {
- if ( typeof url !== "string" && _load ) {
- return _load.apply( this, arguments );
- }
-
- var selector, response, type,
+ var selector, type, response,
self = this,
- off = url.indexOf(" ");
+ off = url.indexOf( " " );
- if ( off >= 0 ) {
- selector = jQuery.trim( url.slice( off, url.length ) );
+ if ( off > -1 ) {
+ selector = jQuery.trim( url.slice( off ) );
url = url.slice( 0, off );
}
@@ -9964,14 +9667,16 @@ jQuery.fn.load = function( url, params, callback ) {
// If we have elements to modify, make the request
if ( self.length > 0 ) {
- jQuery.ajax({
+ jQuery.ajax( {
url: url,
- // if "type" variable is undefined, then "GET" method will be used
- type: type,
+ // If "type" variable is undefined, then "GET" method will be used.
+ // Make value of this field explicit since
+ // user can override it through ajaxSetup method
+ type: type || "GET",
dataType: "html",
data: params
- }).done(function( responseText ) {
+ } ).done( function( responseText ) {
// Save response for use in complete callback
response = arguments;
@@ -9980,14 +9685,19 @@ jQuery.fn.load = function( url, params, callback ) {
// If a selector was specified, locate the right elements in a dummy div
// Exclude scripts to avoid IE 'Permission Denied' errors
- jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+ jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
// Otherwise use the full result
responseText );
- }).complete( callback && function( jqXHR, status ) {
- self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
- });
+ // If the request succeeds, this function gets "data", "status", "jqXHR"
+ // but they are ignored because response was set above.
+ // If it fails, this function gets "jqXHR", "status", "error"
+ } ).always( callback && function( jqXHR, status ) {
+ self.each( function() {
+ callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
+ } );
+ } );
}
return this;
@@ -9996,27 +9706,37 @@ jQuery.fn.load = function( url, params, callback ) {
-jQuery.expr.filters.animated = function( elem ) {
- return jQuery.grep(jQuery.timers, function( fn ) {
- return elem === fn.elem;
- }).length;
-};
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [
+ "ajaxStart",
+ "ajaxStop",
+ "ajaxComplete",
+ "ajaxError",
+ "ajaxSuccess",
+ "ajaxSend"
+], function( i, type ) {
+ jQuery.fn[ type ] = function( fn ) {
+ return this.on( type, fn );
+ };
+} );
+jQuery.expr.pseudos.animated = function( elem ) {
+ return jQuery.grep( jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ } ).length;
+};
+
+
-var docElem = window.document.documentElement;
/**
* Gets a window from an element
*/
function getWindow( elem ) {
- return jQuery.isWindow( elem ) ?
- elem :
- elem.nodeType === 9 ?
- elem.defaultView || elem.parentWindow :
- false;
+ return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
}
jQuery.offset = {
@@ -10026,7 +9746,7 @@ jQuery.offset = {
curElem = jQuery( elem ),
props = {};
- // set position first, in-case top/left are set even on static elem
+ // Set position first, in-case top/left are set even on static elem
if ( position === "static" ) {
elem.style.position = "relative";
}
@@ -10035,20 +9755,24 @@ jQuery.offset = {
curCSSTop = jQuery.css( elem, "top" );
curCSSLeft = jQuery.css( elem, "left" );
calculatePosition = ( position === "absolute" || position === "fixed" ) &&
- jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
+ ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
- // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ // Need to be able to calculate position if either
+ // top or left is auto and position is either absolute or fixed
if ( calculatePosition ) {
curPosition = curElem.position();
curTop = curPosition.top;
curLeft = curPosition.left;
+
} else {
curTop = parseFloat( curCSSTop ) || 0;
curLeft = parseFloat( curCSSLeft ) || 0;
}
if ( jQuery.isFunction( options ) ) {
- options = options.call( elem, i, curOffset );
+
+ // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
+ options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
}
if ( options.top != null ) {
@@ -10060,48 +9784,55 @@ jQuery.offset = {
if ( "using" in options ) {
options.using.call( elem, props );
+
} else {
curElem.css( props );
}
}
};
-jQuery.fn.extend({
+jQuery.fn.extend( {
offset: function( options ) {
+
+ // Preserve chaining for setter
if ( arguments.length ) {
return options === undefined ?
this :
- this.each(function( i ) {
+ this.each( function( i ) {
jQuery.offset.setOffset( this, options, i );
- });
+ } );
}
- var docElem, win,
- box = { top: 0, left: 0 },
- elem = this[ 0 ],
- doc = elem && elem.ownerDocument;
+ var docElem, win, rect, doc,
+ elem = this[ 0 ];
- if ( !doc ) {
+ if ( !elem ) {
return;
}
- docElem = doc.documentElement;
-
- // Make sure it's not a disconnected DOM node
- if ( !jQuery.contains( docElem, elem ) ) {
- return box;
+ // Support: IE <=11 only
+ // Running getBoundingClientRect on a
+ // disconnected node in IE throws an error
+ if ( !elem.getClientRects().length ) {
+ return { top: 0, left: 0 };
}
- // If we don't have gBCR, just use 0,0 rather than error
- // BlackBerry 5, iOS 3 (original iPhone)
- if ( typeof elem.getBoundingClientRect !== strundefined ) {
- box = elem.getBoundingClientRect();
+ rect = elem.getBoundingClientRect();
+
+ // Make sure element is not hidden (display: none)
+ if ( rect.width || rect.height ) {
+ doc = elem.ownerDocument;
+ win = getWindow( doc );
+ docElem = doc.documentElement;
+
+ return {
+ top: rect.top + win.pageYOffset - docElem.clientTop,
+ left: rect.left + win.pageXOffset - docElem.clientLeft
+ };
}
- win = getWindow( doc );
- return {
- top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
- left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
- };
+
+ // Return zeros for disconnected and hidden elements (gh-2310)
+ return rect;
},
position: function() {
@@ -10110,14 +9841,18 @@ jQuery.fn.extend({
}
var offsetParent, offset,
- parentOffset = { top: 0, left: 0 },
- elem = this[ 0 ];
+ elem = this[ 0 ],
+ parentOffset = { top: 0, left: 0 };
- // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
+ // Fixed elements are offset from window (parentOffset = {top:0, left: 0},
+ // because it is its only offset parent
if ( jQuery.css( elem, "position" ) === "fixed" ) {
- // we assume that getBoundingClientRect is available when computed position is fixed
+
+ // Assume getBoundingClientRect is there when computed position is fixed
offset = elem.getBoundingClientRect();
+
} else {
+
// Get *real* offsetParent
offsetParent = this.offsetParent();
@@ -10128,81 +9863,95 @@ jQuery.fn.extend({
}
// Add offsetParent borders
- parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
- parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+ parentOffset = {
+ top: parentOffset.top + jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ),
+ left: parentOffset.left + jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true )
+ };
}
// Subtract parent offsets and element margins
- // note: when an element has margin: auto the offsetLeft and marginLeft
- // are the same in Safari causing offset.left to incorrectly be 0
return {
- top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
- left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
};
},
+ // This method will return documentElement in the following cases:
+ // 1) For the element inside the iframe without offsetParent, this method will return
+ // documentElement of the parent window
+ // 2) For the hidden or detached element
+ // 3) For body or html element, i.e. in case of the html node - it will return itself
+ //
+ // but those exceptions were never presented as a real life use-cases
+ // and might be considered as more preferable results.
+ //
+ // This logic, however, is not guaranteed and can change at any point in the future
offsetParent: function() {
- return this.map(function() {
- var offsetParent = this.offsetParent || docElem;
+ return this.map( function() {
+ var offsetParent = this.offsetParent;
- while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
+ while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
offsetParent = offsetParent.offsetParent;
}
- return offsetParent || docElem;
- });
+
+ return offsetParent || documentElement;
+ } );
}
-});
+} );
// Create scrollLeft and scrollTop methods
jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
- var top = /Y/.test( prop );
+ var top = "pageYOffset" === prop;
jQuery.fn[ method ] = function( val ) {
return access( this, function( elem, method, val ) {
var win = getWindow( elem );
if ( val === undefined ) {
- return win ? (prop in win) ? win[ prop ] :
- win.document.documentElement[ method ] :
- elem[ method ];
+ return win ? win[ prop ] : elem[ method ];
}
if ( win ) {
win.scrollTo(
- !top ? val : jQuery( win ).scrollLeft(),
- top ? val : jQuery( win ).scrollTop()
+ !top ? val : win.pageXOffset,
+ top ? val : win.pageYOffset
);
} else {
elem[ method ] = val;
}
- }, method, val, arguments.length, null );
+ }, method, val, arguments.length );
};
-});
+} );
+// Support: Safari <=7 - 9.1, Chrome <=37 - 49
// Add the top/left cssHooks using jQuery.fn.position
// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
-// getComputedStyle returns percent when specified for top/left/bottom/right
-// rather than make the css module depend on the offset module, we just check for it here
+// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
+// getComputedStyle returns percent when specified for top/left/bottom/right;
+// rather than make the css module depend on the offset module, just check for it here
jQuery.each( [ "top", "left" ], function( i, prop ) {
jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
function( elem, computed ) {
if ( computed ) {
computed = curCSS( elem, prop );
- // if curCSS returns percentage, fallback to offset
+
+ // If curCSS returns percentage, fallback to offset
return rnumnonpx.test( computed ) ?
jQuery( elem ).position()[ prop ] + "px" :
computed;
}
}
);
-});
+} );
// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
- jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
- // margin is only for outerHeight, outerWidth
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
+ function( defaultExtra, funcName ) {
+
+ // Margin is only for outerHeight, outerWidth
jQuery.fn[ funcName ] = function( margin, value ) {
var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
@@ -10211,18 +9960,19 @@ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
var doc;
if ( jQuery.isWindow( elem ) ) {
- // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
- // isn't a whole lot we can do. See pull request at this URL for discussion:
- // https://github.com/jquery/jquery/pull/764
- return elem.document.documentElement[ "client" + name ];
+
+ // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
+ return funcName.indexOf( "outer" ) === 0 ?
+ elem[ "inner" + name ] :
+ elem.document.documentElement[ "client" + name ];
}
// Get document width or height
if ( elem.nodeType === 9 ) {
doc = elem.documentElement;
- // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
- // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
+ // whichever is greatest
return Math.max(
elem.body[ "scroll" + name ], doc[ "scroll" + name ],
elem.body[ "offset" + name ], doc[ "offset" + name ],
@@ -10231,23 +9981,40 @@ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
}
return value === undefined ?
+
// Get width or height on the element, requesting but not forcing parseFloat
jQuery.css( elem, type, extra ) :
// Set width or height on the element
jQuery.style( elem, type, value, extra );
- }, type, chainable ? margin : undefined, chainable, null );
+ }, type, chainable ? margin : undefined, chainable );
};
- });
-});
+ } );
+} );
-// The number of elements contained in the matched element set
-jQuery.fn.size = function() {
- return this.length;
-};
+jQuery.fn.extend( {
-jQuery.fn.andSelf = jQuery.fn.addBack;
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length === 1 ?
+ this.off( selector, "**" ) :
+ this.off( types, selector || "**", fn );
+ }
+} );
+
+jQuery.parseJSON = JSON.parse;
@@ -10268,13 +10035,15 @@ jQuery.fn.andSelf = jQuery.fn.addBack;
if ( typeof define === "function" && define.amd ) {
define( "jquery", [], function() {
return jQuery;
- });
+ } );
}
+
var
+
// Map over jQuery in case of overwrite
_jQuery = window.jQuery,
@@ -10293,16 +10062,13 @@ jQuery.noConflict = function( deep ) {
return jQuery;
};
-// Expose jQuery and $ identifiers, even in
-// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// Expose jQuery and $ identifiers, even in AMD
+// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (#13566)
-if ( typeof noGlobal === strundefined ) {
+if ( !noGlobal ) {
window.jQuery = window.$ = jQuery;
}
-
-
return jQuery;
-
-}));
+} );
diff --git a/sphinx/themes/basic/static/jquery.js b/sphinx/themes/basic/static/jquery.js
index ab28a2472..f6a6a99e6 100644
--- a/sphinx/themes/basic/static/jquery.js
+++ b/sphinx/themes/basic/static/jquery.js
@@ -1,4 +1,4 @@
-/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
-!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="<div class='a'></div><div class='a i'></div>",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="<select msallowclip=''><option selected=''></option></select>",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=lb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=mb(b);function pb(){}pb.prototype=d.filters=d.pseudos,d.setFilters=new pb,g=fb.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fb.error(a):z(a,i).slice(0)};function qb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;
-if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?m.queue(this[0],a):void 0===b?this:this.each(function(){var c=m.queue(this,a,b);m._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&m.dequeue(this,a)})},dequeue:function(a){return this.each(function(){m.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=m.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=m._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=["Top","Right","Bottom","Left"],U=function(a,b){return a=b||a,"none"===m.css(a,"display")||!m.contains(a.ownerDocument,a)},V=m.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===m.type(c)){e=!0;for(h in c)m.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,m.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(m(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav></:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[m.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=Z.test(e)?this.mouseHooks:Y.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new m.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||y),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||y,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==cb()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===cb()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return m.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return m.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=m.extend(new m.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?m.event.trigger(e,null,b):m.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},m.removeEvent=y.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===K&&(a[d]=null),a.detachEvent(d,c))},m.Event=function(a,b){return this instanceof m.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ab:bb):this.type=a,b&&m.extend(this,b),this.timeStamp=a&&a.timeStamp||m.now(),void(this[m.expando]=!0)):new m.Event(a,b)},m.Event.prototype={isDefaultPrevented:bb,isPropagationStopped:bb,isImmediatePropagationStopped:bb,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ab,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ab,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ab,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},m.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){m.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!m.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.submitBubbles||(m.event.special.submit={setup:function(){return m.nodeName(this,"form")?!1:void m.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=m.nodeName(b,"input")||m.nodeName(b,"button")?b.form:void 0;c&&!m._data(c,"submitBubbles")&&(m.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),m._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&m.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return m.nodeName(this,"form")?!1:void m.event.remove(this,"._submit")}}),k.changeBubbles||(m.event.special.change={setup:function(){return X.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(m.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),m.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),m.event.simulate("change",this,a,!0)})),!1):void m.event.add(this,"beforeactivate._change",function(a){var b=a.target;X.test(b.nodeName)&&!m._data(b,"changeBubbles")&&(m.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||m.event.simulate("change",this.parentNode,a,!0)}),m._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return m.event.remove(this,"._change"),!X.test(this.nodeName)}}),k.focusinBubbles||m.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){m.event.simulate(b,a.target,m.event.fix(a),!0)};m.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=m._data(d,b);e||d.addEventListener(a,c,!0),m._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=m._data(d,b)-1;e?m._data(d,b,e):(d.removeEventListener(a,c,!0),m._removeData(d,b))}}}),m.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(f in a)this.on(f,b,c,a[f],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=bb;else if(!d)return this;return 1===e&&(g=d,d=function(a){return m().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=m.guid++)),this.each(function(){m.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,m(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=bb),this.each(function(){m.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){m.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?m.event.trigger(a,b,c,!0):void 0}});function db(a){var b=eb.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var eb="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",fb=/ jQuery\d+="(?:null|\d+)"/g,gb=new RegExp("<(?:"+eb+")[\\s/>]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/<tbody/i,lb=/<|&#?\w+;/,mb=/<(?:script|style|link)/i,nb=/checked\s*(?:[^=]|=\s*.checked.)/i,ob=/^$|\/(?:java|ecma)script/i,pb=/^true\/(.*)/,qb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,rb={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:k.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1></$2>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?"<table>"!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Cb[0].contentWindow||Cb[0].contentDocument).document,b.write(),b.close(),c=Eb(a,b),Cb.detach()),Db[a]=c),c}!function(){var a;k.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,d;return c=y.getElementsByTagName("body")[0],c&&c.style?(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(y.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(d),a):void 0}}();var Gb=/^margin/,Hb=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ib,Jb,Kb=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ib=function(a){return a.ownerDocument.defaultView.getComputedStyle(a,null)},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||m.contains(a.ownerDocument,a)||(g=m.style(a,b)),Hb.test(g)&&Gb.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):y.documentElement.currentStyle&&(Ib=function(a){return a.currentStyle},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Hb.test(g)&&!Kb.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Lb(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h;if(b=y.createElement("div"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=d&&d.style){c.cssText="float:left;opacity:.5",k.opacity="0.5"===c.opacity,k.cssFloat=!!c.cssFloat,b.style.backgroundClip="content-box",b.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===b.style.backgroundClip,k.boxSizing=""===c.boxSizing||""===c.MozBoxSizing||""===c.WebkitBoxSizing,m.extend(k,{reliableHiddenOffsets:function(){return null==g&&i(),g},boxSizingReliable:function(){return null==f&&i(),f},pixelPosition:function(){return null==e&&i(),e},reliableMarginRight:function(){return null==h&&i(),h}});function i(){var b,c,d,i;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),b.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",e=f=!1,h=!0,a.getComputedStyle&&(e="1%"!==(a.getComputedStyle(b,null)||{}).top,f="4px"===(a.getComputedStyle(b,null)||{width:"4px"}).width,i=b.appendChild(y.createElement("div")),i.style.cssText=b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",b.style.width="1px",h=!parseFloat((a.getComputedStyle(i,null)||{}).marginRight)),b.innerHTML="<table><tr><td></td><td>t</td></tr></table>",i=b.getElementsByTagName("td"),i[0].style.cssText="margin:0;border:0;padding:0;display:none",g=0===i[0].offsetHeight,g&&(i[0].style.display="",i[1].style.display="none",g=0===i[0].offsetHeight),c.removeChild(d))}}}(),m.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Mb=/alpha\([^)]*\)/i,Nb=/opacity\s*=\s*([^)]*)/,Ob=/^(none|table(?!-c[ea]).+)/,Pb=new RegExp("^("+S+")(.*)$","i"),Qb=new RegExp("^([+-])=("+S+")","i"),Rb={position:"absolute",visibility:"hidden",display:"block"},Sb={letterSpacing:"0",fontWeight:"400"},Tb=["Webkit","O","Moz","ms"];function Ub(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Tb.length;while(e--)if(b=Tb[e]+c,b in a)return b;return d}function Vb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=m._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&U(d)&&(f[g]=m._data(d,"olddisplay",Fb(d.nodeName)))):(e=U(d),(c&&"none"!==c||!e)&&m._data(d,"olddisplay",e?c:m.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Wb(a,b,c){var d=Pb.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Xb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=m.css(a,c+T[f],!0,e)),d?("content"===c&&(g-=m.css(a,"padding"+T[f],!0,e)),"margin"!==c&&(g-=m.css(a,"border"+T[f]+"Width",!0,e))):(g+=m.css(a,"padding"+T[f],!0,e),"padding"!==c&&(g+=m.css(a,"border"+T[f]+"Width",!0,e)));return g}function Yb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ib(a),g=k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Jb(a,b,f),(0>e||null==e)&&(e=a.style[b]),Hb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Xb(a,b,c||(g?"border":"content"),d,f)+"px"}m.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Jb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":k.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=m.camelCase(b),i=a.style;if(b=m.cssProps[h]||(m.cssProps[h]=Ub(i,h)),g=m.cssHooks[b]||m.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Qb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(m.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||m.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=m.camelCase(b);return b=m.cssProps[h]||(m.cssProps[h]=Ub(a.style,h)),g=m.cssHooks[b]||m.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Jb(a,b,d)),"normal"===f&&b in Sb&&(f=Sb[b]),""===c||c?(e=parseFloat(f),c===!0||m.isNumeric(e)?e||0:f):f}}),m.each(["height","width"],function(a,b){m.cssHooks[b]={get:function(a,c,d){return c?Ob.test(m.css(a,"display"))&&0===a.offsetWidth?m.swap(a,Rb,function(){return Yb(a,b,d)}):Yb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ib(a);return Wb(a,c,d?Xb(a,b,d,k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,e),e):0)}}}),k.opacity||(m.cssHooks.opacity={get:function(a,b){return Nb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=m.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===m.trim(f.replace(Mb,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Mb.test(f)?f.replace(Mb,e):f+" "+e)}}),m.cssHooks.marginRight=Lb(k.reliableMarginRight,function(a,b){return b?m.swap(a,{display:"inline-block"},Jb,[a,"marginRight"]):void 0}),m.each({margin:"",padding:"",border:"Width"},function(a,b){m.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+T[d]+b]=f[d]||f[d-2]||f[0];return e}},Gb.test(a)||(m.cssHooks[a+b].set=Wb)}),m.fn.extend({css:function(a,b){return V(this,function(a,b,c){var d,e,f={},g=0;if(m.isArray(b)){for(d=Ib(a),e=b.length;e>g;g++)f[b[g]]=m.css(a,b[g],!1,d);return f}return void 0!==c?m.style(a,b,c):m.css(a,b)},a,b,arguments.length>1)},show:function(){return Vb(this,!0)},hide:function(){return Vb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){U(this)?m(this).show():m(this).hide()})}});function Zb(a,b,c,d,e){return new Zb.prototype.init(a,b,c,d,e)}m.Tween=Zb,Zb.prototype={constructor:Zb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(m.cssNumber[c]?"":"px")
-},cur:function(){var a=Zb.propHooks[this.prop];return a&&a.get?a.get(this):Zb.propHooks._default.get(this)},run:function(a){var b,c=Zb.propHooks[this.prop];return this.pos=b=this.options.duration?m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Zb.propHooks._default.set(this),this}},Zb.prototype.init.prototype=Zb.prototype,Zb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=m.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){m.fx.step[a.prop]?m.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[m.cssProps[a.prop]]||m.cssHooks[a.prop])?m.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Zb.propHooks.scrollTop=Zb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},m.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},m.fx=Zb.prototype.init,m.fx.step={};var $b,_b,ac=/^(?:toggle|show|hide)$/,bc=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),cc=/queueHooks$/,dc=[ic],ec={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bc.exec(b),f=e&&e[3]||(m.cssNumber[a]?"":"px"),g=(m.cssNumber[a]||"px"!==f&&+d)&&bc.exec(m.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,m.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function fc(){return setTimeout(function(){$b=void 0}),$b=m.now()}function gc(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=T[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function hc(a,b,c){for(var d,e=(ec[b]||[]).concat(ec["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ic(a,b,c){var d,e,f,g,h,i,j,l,n=this,o={},p=a.style,q=a.nodeType&&U(a),r=m._data(a,"fxshow");c.queue||(h=m._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,n.always(function(){n.always(function(){h.unqueued--,m.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=m.css(a,"display"),l="none"===j?m._data(a,"olddisplay")||Fb(a.nodeName):j,"inline"===l&&"none"===m.css(a,"float")&&(k.inlineBlockNeedsLayout&&"inline"!==Fb(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",k.shrinkWrapBlocks()||n.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ac.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||m.style(a,d)}else j=void 0;if(m.isEmptyObject(o))"inline"===("none"===j?Fb(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=m._data(a,"fxshow",{}),f&&(r.hidden=!q),q?m(a).show():n.done(function(){m(a).hide()}),n.done(function(){var b;m._removeData(a,"fxshow");for(b in o)m.style(a,b,o[b])});for(d in o)g=hc(q?r[d]:0,d,n),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function jc(a,b){var c,d,e,f,g;for(c in a)if(d=m.camelCase(c),e=b[d],f=a[c],m.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=m.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kc(a,b,c){var d,e,f=0,g=dc.length,h=m.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$b||fc(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:m.extend({},b),opts:m.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:$b||fc(),duration:c.duration,tweens:[],createTween:function(b,c){var d=m.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jc(k,j.opts.specialEasing);g>f;f++)if(d=dc[f].call(j,a,k,j.opts))return d;return m.map(k,hc,j),m.isFunction(j.opts.start)&&j.opts.start.call(a,j),m.fx.timer(m.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}m.Animation=m.extend(kc,{tweener:function(a,b){m.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],ec[c]=ec[c]||[],ec[c].unshift(b)},prefilter:function(a,b){b?dc.unshift(a):dc.push(a)}}),m.speed=function(a,b,c){var d=a&&"object"==typeof a?m.extend({},a):{complete:c||!c&&b||m.isFunction(a)&&a,duration:a,easing:c&&b||b&&!m.isFunction(b)&&b};return d.duration=m.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in m.fx.speeds?m.fx.speeds[d.duration]:m.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){m.isFunction(d.old)&&d.old.call(this),d.queue&&m.dequeue(this,d.queue)},d},m.fn.extend({fadeTo:function(a,b,c,d){return this.filter(U).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=m.isEmptyObject(a),f=m.speed(b,c,d),g=function(){var b=kc(this,m.extend({},a),f);(e||m._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=m.timers,g=m._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&cc.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&m.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=m._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=m.timers,g=d?d.length:0;for(c.finish=!0,m.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),m.each(["toggle","show","hide"],function(a,b){var c=m.fn[b];m.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gc(b,!0),a,d,e)}}),m.each({slideDown:gc("show"),slideUp:gc("hide"),slideToggle:gc("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){m.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),m.timers=[],m.fx.tick=function(){var a,b=m.timers,c=0;for($b=m.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||m.fx.stop(),$b=void 0},m.fx.timer=function(a){m.timers.push(a),a()?m.fx.start():m.timers.pop()},m.fx.interval=13,m.fx.start=function(){_b||(_b=setInterval(m.fx.tick,m.fx.interval))},m.fx.stop=function(){clearInterval(_b),_b=null},m.fx.speeds={slow:600,fast:200,_default:400},m.fn.delay=function(a,b){return a=m.fx?m.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a,b,c,d,e;b=y.createElement("div"),b.setAttribute("className","t"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=y.createElement("select"),e=c.appendChild(y.createElement("option")),a=b.getElementsByTagName("input")[0],d.style.cssText="top:1px",k.getSetAttribute="t"!==b.className,k.style=/top/.test(d.getAttribute("style")),k.hrefNormalized="/a"===d.getAttribute("href"),k.checkOn=!!a.value,k.optSelected=e.selected,k.enctype=!!y.createElement("form").enctype,c.disabled=!0,k.optDisabled=!e.disabled,a=y.createElement("input"),a.setAttribute("value",""),k.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),k.radioValue="t"===a.value}();var lc=/\r/g;m.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=m.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,m(this).val()):a,null==e?e="":"number"==typeof e?e+="":m.isArray(e)&&(e=m.map(e,function(a){return null==a?"":a+""})),b=m.valHooks[this.type]||m.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=m.valHooks[e.type]||m.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(lc,""):null==c?"":c)}}}),m.extend({valHooks:{option:{get:function(a){var b=m.find.attr(a,"value");return null!=b?b:m.trim(m.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&m.nodeName(c.parentNode,"optgroup"))){if(b=m(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=m.makeArray(b),g=e.length;while(g--)if(d=e[g],m.inArray(m.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),m.each(["radio","checkbox"],function(){m.valHooks[this]={set:function(a,b){return m.isArray(b)?a.checked=m.inArray(m(a).val(),b)>=0:void 0}},k.checkOn||(m.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var mc,nc,oc=m.expr.attrHandle,pc=/^(?:checked|selected)$/i,qc=k.getSetAttribute,rc=k.input;m.fn.extend({attr:function(a,b){return V(this,m.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){m.removeAttr(this,a)})}}),m.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===K?m.prop(a,b,c):(1===f&&m.isXMLDoc(a)||(b=b.toLowerCase(),d=m.attrHooks[b]||(m.expr.match.bool.test(b)?nc:mc)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=m.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void m.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=m.propFix[c]||c,m.expr.match.bool.test(c)?rc&&qc||!pc.test(c)?a[d]=!1:a[m.camelCase("default-"+c)]=a[d]=!1:m.attr(a,c,""),a.removeAttribute(qc?c:d)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&m.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),nc={set:function(a,b,c){return b===!1?m.removeAttr(a,c):rc&&qc||!pc.test(c)?a.setAttribute(!qc&&m.propFix[c]||c,c):a[m.camelCase("default-"+c)]=a[c]=!0,c}},m.each(m.expr.match.bool.source.match(/\w+/g),function(a,b){var c=oc[b]||m.find.attr;oc[b]=rc&&qc||!pc.test(b)?function(a,b,d){var e,f;return d||(f=oc[b],oc[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,oc[b]=f),e}:function(a,b,c){return c?void 0:a[m.camelCase("default-"+b)]?b.toLowerCase():null}}),rc&&qc||(m.attrHooks.value={set:function(a,b,c){return m.nodeName(a,"input")?void(a.defaultValue=b):mc&&mc.set(a,b,c)}}),qc||(mc={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},oc.id=oc.name=oc.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},m.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:mc.set},m.attrHooks.contenteditable={set:function(a,b,c){mc.set(a,""===b?!1:b,c)}},m.each(["width","height"],function(a,b){m.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),k.style||(m.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var sc=/^(?:input|select|textarea|button|object)$/i,tc=/^(?:a|area)$/i;m.fn.extend({prop:function(a,b){return V(this,m.prop,a,b,arguments.length>1)},removeProp:function(a){return a=m.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),m.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!m.isXMLDoc(a),f&&(b=m.propFix[b]||b,e=m.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=m.find.attr(a,"tabindex");return b?parseInt(b,10):sc.test(a.nodeName)||tc.test(a.nodeName)&&a.href?0:-1}}}}),k.hrefNormalized||m.each(["href","src"],function(a,b){m.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),k.optSelected||(m.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),m.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){m.propFix[this.toLowerCase()]=this}),k.enctype||(m.propFix.enctype="encoding");var uc=/[\t\r\n\f]/g;m.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=m.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?m.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(m.isFunction(a)?function(c){m(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=m(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===K||"boolean"===c)&&(this.className&&m._data(this,"__className__",this.className),this.className=this.className||a===!1?"":m._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(uc," ").indexOf(b)>=0)return!0;return!1}}),m.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){m.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),m.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var vc=m.now(),wc=/\?/,xc=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;m.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=m.trim(b+"");return e&&!m.trim(e.replace(xc,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():m.error("Invalid JSON: "+b)},m.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||m.error("Invalid XML: "+b),c};var yc,zc,Ac=/#.*$/,Bc=/([?&])_=[^&]*/,Cc=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Dc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Ec=/^(?:GET|HEAD)$/,Fc=/^\/\//,Gc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Hc={},Ic={},Jc="*/".concat("*");try{zc=location.href}catch(Kc){zc=y.createElement("a"),zc.href="",zc=zc.href}yc=Gc.exec(zc.toLowerCase())||[];function Lc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(m.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Mc(a,b,c,d){var e={},f=a===Ic;function g(h){var i;return e[h]=!0,m.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Nc(a,b){var c,d,e=m.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&m.extend(!0,a,c),a}function Oc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Pc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}m.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:zc,type:"GET",isLocal:Dc.test(yc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Jc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":m.parseJSON,"text xml":m.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Nc(Nc(a,m.ajaxSettings),b):Nc(m.ajaxSettings,a)},ajaxPrefilter:Lc(Hc),ajaxTransport:Lc(Ic),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=m.ajaxSetup({},b),l=k.context||k,n=k.context&&(l.nodeType||l.jquery)?m(l):m.event,o=m.Deferred(),p=m.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Cc.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||zc)+"").replace(Ac,"").replace(Fc,yc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=m.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(c=Gc.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===yc[1]&&c[2]===yc[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(yc[3]||("http:"===yc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=m.param(k.data,k.traditional)),Mc(Hc,k,b,v),2===t)return v;h=k.global,h&&0===m.active++&&m.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Ec.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(wc.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Bc.test(e)?e.replace(Bc,"$1_="+vc++):e+(wc.test(e)?"&":"?")+"_="+vc++)),k.ifModified&&(m.lastModified[e]&&v.setRequestHeader("If-Modified-Since",m.lastModified[e]),m.etag[e]&&v.setRequestHeader("If-None-Match",m.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Jc+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Mc(Ic,k,b,v)){v.readyState=1,h&&n.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Oc(k,v,c)),u=Pc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(m.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(m.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&n.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(n.trigger("ajaxComplete",[v,k]),--m.active||m.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return m.get(a,b,c,"json")},getScript:function(a,b){return m.get(a,void 0,b,"script")}}),m.each(["get","post"],function(a,b){m[b]=function(a,c,d,e){return m.isFunction(c)&&(e=e||d,d=c,c=void 0),m.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m._evalUrl=function(a){return m.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},m.fn.extend({wrapAll:function(a){if(m.isFunction(a))return this.each(function(b){m(this).wrapAll(a.call(this,b))});if(this[0]){var b=m(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(m.isFunction(a)?function(b){m(this).wrapInner(a.call(this,b))}:function(){var b=m(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=m.isFunction(a);return this.each(function(c){m(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){m.nodeName(this,"body")||m(this).replaceWith(this.childNodes)}).end()}}),m.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!k.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||m.css(a,"display"))},m.expr.filters.visible=function(a){return!m.expr.filters.hidden(a)};var Qc=/%20/g,Rc=/\[\]$/,Sc=/\r?\n/g,Tc=/^(?:submit|button|image|reset|file)$/i,Uc=/^(?:input|select|textarea|keygen)/i;function Vc(a,b,c,d){var e;if(m.isArray(b))m.each(b,function(b,e){c||Rc.test(a)?d(a,e):Vc(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==m.type(b))d(a,b);else for(e in b)Vc(a+"["+e+"]",b[e],c,d)}m.param=function(a,b){var c,d=[],e=function(a,b){b=m.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=m.ajaxSettings&&m.ajaxSettings.traditional),m.isArray(a)||a.jquery&&!m.isPlainObject(a))m.each(a,function(){e(this.name,this.value)});else for(c in a)Vc(c,a[c],b,e);return d.join("&").replace(Qc,"+")},m.fn.extend({serialize:function(){return m.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=m.prop(this,"elements");return a?m.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!m(this).is(":disabled")&&Uc.test(this.nodeName)&&!Tc.test(a)&&(this.checked||!W.test(a))}).map(function(a,b){var c=m(this).val();return null==c?null:m.isArray(c)?m.map(c,function(a){return{name:b.name,value:a.replace(Sc,"\r\n")}}):{name:b.name,value:c.replace(Sc,"\r\n")}}).get()}}),m.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&Zc()||$c()}:Zc;var Wc=0,Xc={},Yc=m.ajaxSettings.xhr();a.ActiveXObject&&m(a).on("unload",function(){for(var a in Xc)Xc[a](void 0,!0)}),k.cors=!!Yc&&"withCredentials"in Yc,Yc=k.ajax=!!Yc,Yc&&m.ajaxTransport(function(a){if(!a.crossDomain||k.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Wc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Xc[g],b=void 0,f.onreadystatechange=m.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Xc[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function Zc(){try{return new a.XMLHttpRequest}catch(b){}}function $c(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}m.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return m.globalEval(a),a}}}),m.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),m.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=y.head||m("head")[0]||y.documentElement;return{send:function(d,e){b=y.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var _c=[],ad=/(=)\?(?=&|$)|\?\?/;m.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=_c.pop()||m.expando+"_"+vc++;return this[a]=!0,a}}),m.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(ad.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&ad.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=m.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(ad,"$1"+e):b.jsonp!==!1&&(b.url+=(wc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||m.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,_c.push(e)),g&&m.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),m.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||y;var d=u.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=m.buildFragment([a],b,e),e&&e.length&&m(e).remove(),m.merge([],d.childNodes))};var bd=m.fn.load;m.fn.load=function(a,b,c){if("string"!=typeof a&&bd)return bd.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=m.trim(a.slice(h,a.length)),a=a.slice(0,h)),m.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&m.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?m("<div>").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cd=a.document.documentElement;function dd(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dd(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cd;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cd})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dd(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=Lb(k.pixelPosition,function(a,c){return c?(c=Jb(a,b),Hb.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ed=a.jQuery,fd=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fd),b&&a.jQuery===m&&(a.jQuery=ed),m},typeof b===K&&(a.jQuery=a.$=m),m});
+/*! jQuery v3.1.0 | (c) jQuery Foundation | jquery.org/license */
+!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.1.0",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null!=a?a<0?this[a+this.length]:this[a]:f.call(this)},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c<b?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:h,sort:c.sort,splice:c.splice},r.extend=r.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||r.isFunction(g)||(g={}),h===i&&(g=this,h--);h<i;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(r.isPlainObject(d)||(e=r.isArray(d)))?(e?(e=!1,f=c&&r.isArray(c)?c:[]):f=c&&r.isPlainObject(c)?c:{},g[b]=r.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},r.extend({expando:"jQuery"+(q+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===r.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=r.type(a);return("number"===b||"string"===b)&&!isNaN(a-parseFloat(a))},isPlainObject:function(a){var b,c;return!(!a||"[object Object]"!==k.call(a))&&(!(b=e(a))||(c=l.call(b,"constructor")&&b.constructor,"function"==typeof c&&m.call(c)===n))},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?j[k.call(a)]||"object":typeof a},globalEval:function(a){p(a)},camelCase:function(a){return a.replace(t,"ms-").replace(u,v)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(w(a)){for(c=a.length;d<c;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(s,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(w(Object(a))?r.merge(c,"string"==typeof a?[a]:a):h.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:i.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;d<c;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;f<g;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,f=0,h=[];if(w(a))for(d=a.length;f<d;f++)e=b(a[f],f,c),null!=e&&h.push(e);else for(f in a)e=b(a[f],f,c),null!=e&&h.push(e);return g.apply([],h)},guid:1,proxy:function(a,b){var c,d,e;if("string"==typeof b&&(c=a[b],b=a,a=c),r.isFunction(a))return d=f.call(arguments,2),e=function(){return a.apply(b||this,d.concat(f.call(arguments)))},e.guid=a.guid=a.guid||r.guid++,e},now:Date.now,support:o}),"function"==typeof Symbol&&(r.fn[Symbol.iterator]=c[Symbol.iterator]),r.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){j["[object "+b+"]"]=b.toLowerCase()});function w(a){var b=!!a&&"length"in a&&a.length,c=r.type(a);return"function"!==c&&!r.isWindow(a)&&("array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return c;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",M="\\["+K+"*("+L+")(?:"+K+"*([*^$|!~]?=)"+K+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+L+"))|)"+K+"*\\]",N=":("+L+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+M+")*)|.*)\\)|)",O=new RegExp(K+"+","g"),P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"label"in b&&b.disabled===a||"form"in b&&b.disabled===a||"form"in b&&b.disabled===!1&&(b.isDisabled===a||b.isDisabled!==!a&&("label"in b||!ea(b))!==a)}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c<b;c+=2)a.push(c);return a}),odd:pa(function(a,b){for(var c=1;c<b;c+=2)a.push(c);return a}),lt:pa(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function ra(){}ra.prototype=d.filters=d.pseudos,d.setFilters=new ra,g=ga.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=Q.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=R.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(P," ")}),h=h.slice(c.length));for(g in d.filter)!(e=V[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function sa(a){for(var b=0,c=a.length,d="";b<c;b++)d+=a[b].value;return d}function ta(a,b,c){var d=b.dir,e=b.next,f=e||d,g=c&&"parentNode"===f,h=x++;return b.first?function(b,c,e){while(b=b[d])if(1===b.nodeType||g)return a(b,c,e)}:function(b,c,i){var j,k,l,m=[w,h];if(i){while(b=b[d])if((1===b.nodeType||g)&&a(b,c,i))return!0}else while(b=b[d])if(1===b.nodeType||g)if(l=b[u]||(b[u]={}),k=l[b.uniqueID]||(l[b.uniqueID]={}),e&&e===b.nodeName.toLowerCase())b=b[d]||b;else{if((j=k[f])&&j[0]===w&&j[1]===h)return m[2]=j[2];if(k[f]=m,m[2]=a(b,c,i))return!0}}}function ua(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d<e;d++)ga(a,b[d],c);return c}function wa(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;h<i;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function xa(a,b,c,d,e,f){return d&&!d[u]&&(d=xa(d)),e&&!e[u]&&(e=xa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||va(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:wa(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=wa(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i<f;i++)if(c=d.relative[a[i].type])m=[ta(ua(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;e<f;e++)if(d.relative[a[e].type])break;return xa(i>1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i<e&&ya(a.slice(i,e)),e<f&&ya(a=a.slice(e)),e<f&&sa(a))}m.push(c)}return ua(m)}function za(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(_,aa),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=V.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(_,aa),$.test(j[0].type)&&qa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&sa(j),!a)return G.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||$.test(a)&&qa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){if(r.isFunction(b))return r.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return r.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(C.test(b))return r.filter(b,a,c);b=r.filter(b,a)}return r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType})}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b<d;b++)if(r.contains(e[b],this))return!0}));for(c=this.pushStack([]),b=0;b<d;b++)r.find(a,e[b],c);return d>1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a<c;a++)if(r.contains(this,b[a]))return!0})},closest:function(a,b){var c,d=0,e=this.length,f=[],g="string"!=typeof a&&r(a);if(!A.test(a))for(;d<e;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/\S+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){r.each(b,function(b,c){r.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==r.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return r.each(arguments,function(a,b){var c;while((c=r.inArray(b,f,c))>-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b<f)){if(a=d.apply(h,i),a===c.promise())throw new TypeError("Thenable self-resolution");j=a&&("object"==typeof a||"function"==typeof a)&&a.then,r.isFunction(j)?e?j.call(a,g(f,c,M,e),g(f,c,N,e)):(f++,j.call(a,g(f,c,M,e),g(f,c,N,e),g(f,c,M,c.notifyWith))):(d!==M&&(h=void 0,i=[a]),(e||c.resolveWith)(h,i))}},k=e?j:function(){try{j()}catch(a){r.Deferred.exceptionHook&&r.Deferred.exceptionHook(a,k.stackTrace),b+1>=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R),a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R),a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,
+r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h<i;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},T=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function U(){this.expando=r.expando+U.uid++}U.uid=1,U.prototype={cache:function(a){var b=a[this.expando];return b||(b={},T(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[r.camelCase(b)]=c;else for(d in b)e[r.camelCase(d)]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][r.camelCase(b)]},access:function(a,b,c){return void 0===b||b&&"string"==typeof b&&void 0===c?this.get(a,b):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d=a[this.expando];if(void 0!==d){if(void 0!==b){r.isArray(b)?b=b.map(r.camelCase):(b=r.camelCase(b),b=b in d?[b]:b.match(K)||[]),c=b.length;while(c--)delete d[b[c]]}(void 0===b||r.isEmptyObject(d))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!r.isEmptyObject(b)}};var V=new U,W=new U,X=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Y=/[A-Z]/g;function Z(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Y,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c||"false"!==c&&("null"===c?null:+c+""===c?+c:X.test(c)?JSON.parse(c):c)}catch(e){}W.set(a,b,c)}else c=void 0;return c}r.extend({hasData:function(a){return W.hasData(a)||V.hasData(a)},data:function(a,b,c){return W.access(a,b,c)},removeData:function(a,b){W.remove(a,b)},_data:function(a,b,c){return V.access(a,b,c)},_removeData:function(a,b){V.remove(a,b)}}),r.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=W.get(f),1===f.nodeType&&!V.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=r.camelCase(d.slice(5)),Z(f,d,e[d])));V.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){W.set(this,a)}):S(this,function(b){var c;if(f&&void 0===b){if(c=W.get(f,a),void 0!==c)return c;if(c=Z(f,a),void 0!==c)return c}else this.each(function(){W.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?r.queue(this[0],a):void 0===b?this:this.each(function(){var c=r.queue(this,a,b);r._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&r.dequeue(this,a)})},dequeue:function(a){return this.each(function(){r.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=r.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=V.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var $=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,_=new RegExp("^(?:([+-])=|)("+$+")([a-z%]*)$","i"),aa=["Top","Right","Bottom","Left"],ba=function(a,b){return a=b||a,"none"===a.style.display||""===a.style.display&&r.contains(a.ownerDocument,a)&&"none"===r.css(a,"display")},ca=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};function da(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return r.css(a,b,"")},i=h(),j=c&&c[3]||(r.cssNumber[b]?"":"px"),k=(r.cssNumber[b]||"px"!==j&&+i)&&_.exec(r.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,r.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var ea={};function fa(a){var b,c=a.ownerDocument,d=a.nodeName,e=ea[d];return e?e:(b=c.body.appendChild(c.createElement(d)),e=r.css(b,"display"),b.parentNode.removeChild(b),"none"===e&&(e="block"),ea[d]=e,e)}function ga(a,b){for(var c,d,e=[],f=0,g=a.length;f<g;f++)d=a[f],d.style&&(c=d.style.display,b?("none"===c&&(e[f]=V.get(d,"display")||null,e[f]||(d.style.display="")),""===d.style.display&&ba(d)&&(e[f]=fa(d))):"none"!==c&&(e[f]="none",V.set(d,"display",c)));for(f=0;f<g;f++)null!=e[f]&&(a[f].style.display=e[f]);return a}r.fn.extend({show:function(){return ga(this,!0)},hide:function(){return ga(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){ba(this)?r(this).show():r(this).hide()})}});var ha=/^(?:checkbox|radio)$/i,ia=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,ja=/^$|\/(?:java|ecma)script/i,ka={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ka.optgroup=ka.option,ka.tbody=ka.tfoot=ka.colgroup=ka.caption=ka.thead,ka.th=ka.td;function la(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function ma(a,b){for(var c=0,d=a.length;c<d;c++)V.set(a[c],"globalEval",!b||V.get(b[c],"globalEval"))}var na=/<|&#?\w+;/;function oa(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],n=0,o=a.length;n<o;n++)if(f=a[n],f||0===f)if("object"===r.type(f))r.merge(m,f.nodeType?[f]:f);else if(na.test(f)){g=g||l.appendChild(b.createElement("div")),h=(ia.exec(f)||["",""])[1].toLowerCase(),i=ka[h]||ka._default,g.innerHTML=i[1]+r.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;r.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",n=0;while(f=m[n++])if(d&&r.inArray(f,d)>-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=la(l.appendChild(f),"script"),j&&ma(g),c){k=0;while(f=g[k++])ja.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var pa=d.documentElement,qa=/^key/,ra=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,sa=/^([^.]*)(?:\.(.+)|)/;function ta(){return!0}function ua(){return!1}function va(){try{return d.activeElement}catch(a){}}function wa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)wa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ua;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(pa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c<arguments.length;c++)i[c]=arguments[c];if(b.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,b)!==!1){h=r.event.handlers.call(this,b,j),c=0;while((f=h[c++])&&!b.isPropagationStopped()){b.currentTarget=f.elem,d=0;while((g=f.handlers[d++])&&!b.isImmediatePropagationStopped())b.rnamespace&&!b.rnamespace.test(g.namespace)||(b.handleObj=g,b.data=g.data,e=((r.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(b.result=e)===!1&&(b.preventDefault(),b.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,b),b.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;c<h;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?r(e,this).index(i)>-1:r.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},addProp:function(a,b){Object.defineProperty(r.Event.prototype,a,{enumerable:!0,configurable:!0,get:r.isFunction(b)?function(){if(this.originalEvent)return b(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[a]},set:function(b){Object.defineProperty(this,a,{enumerable:!0,configurable:!0,writable:!0,value:b})}})},fix:function(a){return a[r.expando]?a:new r.Event(a)},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==va()&&this.focus)return this.focus(),!1},delegateType:"focusin"},blur:{trigger:function(){if(this===va()&&this.blur)return this.blur(),!1},delegateType:"focusout"},click:{trigger:function(){if("checkbox"===this.type&&this.click&&r.nodeName(this,"input"))return this.click(),!1},_default:function(a){return r.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}}},r.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)},r.Event=function(a,b){return this instanceof r.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ta:ua,this.target=a.target&&3===a.target.nodeType?a.target.parentNode:a.target,this.currentTarget=a.currentTarget,this.relatedTarget=a.relatedTarget):this.type=a,b&&r.extend(this,b),this.timeStamp=a&&a.timeStamp||r.now(),void(this[r.expando]=!0)):new r.Event(a,b)},r.Event.prototype={constructor:r.Event,isDefaultPrevented:ua,isPropagationStopped:ua,isImmediatePropagationStopped:ua,isSimulated:!1,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ta,a&&!this.isSimulated&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ta,a&&!this.isSimulated&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ta,a&&!this.isSimulated&&a.stopImmediatePropagation(),this.stopPropagation()}},r.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(a){var b=a.button;return null==a.which&&qa.test(a.type)?null!=a.charCode?a.charCode:a.keyCode:!a.which&&void 0!==b&&ra.test(a.type)?1&b?1:2&b?3:4&b?2:0:a.which}},r.event.addProp),r.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){r.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||r.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),r.fn.extend({on:function(a,b,c,d){return wa(this,a,b,c,d)},one:function(a,b,c,d){return wa(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,r(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=ua),this.each(function(){r.event.remove(this,a,c,b)})}});var xa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,ya=/<script|<style|<link/i,za=/checked\s*(?:[^=]|=\s*.checked.)/i,Aa=/^true\/(.*)/,Ba=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Ca(a,b){return r.nodeName(a,"table")&&r.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function Da(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ea(a){var b=Aa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(V.hasData(a)&&(f=V.access(a),g=V.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c<d;c++)r.event.add(b,e,j[e][c])}W.hasData(a)&&(h=W.access(a),i=r.extend({},h),W.set(b,i))}}function Ga(a,b){var c=b.nodeName.toLowerCase();"input"===c&&ha.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function Ha(a,b,c,d){b=g.apply([],b);var e,f,h,i,j,k,l=0,m=a.length,n=m-1,q=b[0],s=r.isFunction(q);if(s||m>1&&"string"==typeof q&&!o.checkClone&&za.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(m&&(e=oa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(la(e,"script"),Da),i=h.length;l<m;l++)j=e,l!==n&&(j=r.clone(j,!0,!0),i&&r.merge(h,la(j,"script"))),c.call(a[l],j,l);if(i)for(k=h[h.length-1].ownerDocument,r.map(h,Ea),l=0;l<i;l++)j=h[l],ja.test(j.type||"")&&!V.access(j,"globalEval")&&r.contains(k,j)&&(j.src?r._evalUrl&&r._evalUrl(j.src):p(j.textContent.replace(Ba,""),k))}return a}function Ia(a,b,c){for(var d,e=b?r.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||r.cleanData(la(d)),d.parentNode&&(c&&r.contains(d.ownerDocument,d)&&ma(la(d,"script")),d.parentNode.removeChild(d));return a}r.extend({htmlPrefilter:function(a){return a.replace(xa,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=la(h),f=la(a),d=0,e=f.length;d<e;d++)Ga(f[d],g[d]);if(b)if(c)for(f=f||la(a),g=g||la(h),d=0,e=f.length;d<e;d++)Fa(f[d],g[d]);else Fa(a,h);return g=la(h,"script"),g.length>0&&ma(g,!i&&la(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(T(c)){if(b=c[V.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[V.expando]=void 0}c[W.expando]&&(c[W.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return S(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(la(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return S(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!ya.test(a)&&!ka[(ia.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c<d;c++)b=this[c]||{},1===b.nodeType&&(r.cleanData(la(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;r.inArray(this,a)<0&&(r.cleanData(la(this)),c&&c.replaceChild(b,this))},a)}}),r.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){r.fn[a]=function(a){for(var c,d=[],e=r(a),f=e.length-1,g=0;g<=f;g++)c=g===f?this:this.clone(!0),r(e[g])[b](c),h.apply(d,c.get());return this.pushStack(d)}});var Ja=/^margin/,Ka=new RegExp("^("+$+")(?!px)[a-z%]+$","i"),La=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)};!function(){function b(){if(i){i.style.cssText="box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",i.innerHTML="",pa.appendChild(h);var b=a.getComputedStyle(i);c="1%"!==b.top,g="2px"===b.marginLeft,e="4px"===b.width,i.style.marginRight="50%",f="4px"===b.marginRight,pa.removeChild(h),i=null}}var c,e,f,g,h=d.createElement("div"),i=d.createElement("div");i.style&&(i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",o.clearCloneStyle="content-box"===i.style.backgroundClip,h.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",h.appendChild(i),r.extend(o,{pixelPosition:function(){return b(),c},boxSizingReliable:function(){return b(),e},pixelMarginRight:function(){return b(),f},reliableMarginLeft:function(){return b(),g}}))}();function Ma(a,b,c){var d,e,f,g,h=a.style;return c=c||La(a),c&&(g=c.getPropertyValue(b)||c[b],""!==g||r.contains(a.ownerDocument,a)||(g=r.style(a,b)),!o.pixelMarginRight()&&Ka.test(g)&&Ja.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function Na(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Oa=/^(none|table(?!-c[ea]).+)/,Pa={position:"absolute",visibility:"hidden",display:"block"},Qa={letterSpacing:"0",fontWeight:"400"},Ra=["Webkit","Moz","ms"],Sa=d.createElement("div").style;function Ta(a){if(a in Sa)return a;var b=a[0].toUpperCase()+a.slice(1),c=Ra.length;while(c--)if(a=Ra[c]+b,a in Sa)return a}function Ua(a,b,c){var d=_.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Va(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;f<4;f+=2)"margin"===c&&(g+=r.css(a,c+aa[f],!0,e)),d?("content"===c&&(g-=r.css(a,"padding"+aa[f],!0,e)),"margin"!==c&&(g-=r.css(a,"border"+aa[f]+"Width",!0,e))):(g+=r.css(a,"padding"+aa[f],!0,e),"padding"!==c&&(g+=r.css(a,"border"+aa[f]+"Width",!0,e)));return g}function Wa(a,b,c){var d,e=!0,f=La(a),g="border-box"===r.css(a,"boxSizing",!1,f);if(a.getClientRects().length&&(d=a.getBoundingClientRect()[b]),d<=0||null==d){if(d=Ma(a,b,f),(d<0||null==d)&&(d=a.style[b]),Ka.test(d))return d;e=g&&(o.boxSizingReliable()||d===a.style[b]),d=parseFloat(d)||0}return d+Va(a,b,c||(g?"border":"content"),e,f)+"px"}r.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Ma(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=r.camelCase(b),i=a.style;return b=r.cssProps[h]||(r.cssProps[h]=Ta(h)||h),g=r.cssHooks[b]||r.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=_.exec(c))&&e[1]&&(c=da(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(r.cssNumber[h]?"":"px")),o.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=r.camelCase(b);return b=r.cssProps[h]||(r.cssProps[h]=Ta(h)||h),g=r.cssHooks[b]||r.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Ma(a,b,d)),"normal"===e&&b in Qa&&(e=Qa[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),r.each(["height","width"],function(a,b){r.cssHooks[b]={get:function(a,c,d){if(c)return!Oa.test(r.css(a,"display"))||a.getClientRects().length&&a.getBoundingClientRect().width?Wa(a,b,d):ca(a,Pa,function(){return Wa(a,b,d)})},set:function(a,c,d){var e,f=d&&La(a),g=d&&Va(a,b,d,"border-box"===r.css(a,"boxSizing",!1,f),f);return g&&(e=_.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=r.css(a,b)),Ua(a,c,g)}}}),r.cssHooks.marginLeft=Na(o.reliableMarginLeft,function(a,b){if(b)return(parseFloat(Ma(a,"marginLeft"))||a.getBoundingClientRect().left-ca(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}))+"px"}),r.each({margin:"",padding:"",border:"Width"},function(a,b){r.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];d<4;d++)e[a+aa[d]+b]=f[d]||f[d-2]||f[0];return e}},Ja.test(a)||(r.cssHooks[a+b].set=Ua)}),r.fn.extend({css:function(a,b){return S(this,function(a,b,c){var d,e,f={},g=0;if(r.isArray(b)){for(d=La(a),e=b.length;g<e;g++)f[b[g]]=r.css(a,b[g],!1,d);return f}return void 0!==c?r.style(a,b,c):r.css(a,b)},a,b,arguments.length>1)}});function Xa(a,b,c,d,e){return new Xa.prototype.init(a,b,c,d,e)}r.Tween=Xa,Xa.prototype={constructor:Xa,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=Xa.propHooks[this.prop];return a&&a.get?a.get(this):Xa.propHooks._default.get(this)},run:function(a){var b,c=Xa.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Xa.propHooks._default.set(this),this}},Xa.prototype.init.prototype=Xa.prototype,Xa.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},Xa.propHooks.scrollTop=Xa.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=Xa.prototype.init,r.fx.step={};var Ya,Za,$a=/^(?:toggle|show|hide)$/,_a=/queueHooks$/;function ab(){Za&&(a.requestAnimationFrame(ab),r.fx.tick())}function bb(){return a.setTimeout(function(){Ya=void 0}),Ya=r.now()}function cb(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=aa[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function db(a,b,c){for(var d,e=(gb.tweeners[b]||[]).concat(gb.tweeners["*"]),f=0,g=e.length;f<g;f++)if(d=e[f].call(c,b,a))return d}function eb(a,b,c){var d,e,f,g,h,i,j,k,l="width"in b||"height"in b,m=this,n={},o=a.style,p=a.nodeType&&ba(a),q=V.get(a,"fxshow");c.queue||(g=r._queueHooks(a,"fx"),null==g.unqueued&&(g.unqueued=0,h=g.empty.fire,g.empty.fire=function(){g.unqueued||h()}),g.unqueued++,m.always(function(){m.always(function(){g.unqueued--,r.queue(a,"fx").length||g.empty.fire()})}));for(d in b)if(e=b[d],$a.test(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}n[d]=q&&q[d]||r.style(a,d)}if(i=!r.isEmptyObject(b),i||!r.isEmptyObject(n)){l&&1===a.nodeType&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=q&&q.display,null==j&&(j=V.get(a,"display")),k=r.css(a,"display"),"none"===k&&(j?k=j:(ga([a],!0),j=a.style.display||j,k=r.css(a,"display"),ga([a]))),("inline"===k||"inline-block"===k&&null!=j)&&"none"===r.css(a,"float")&&(i||(m.done(function(){o.display=j}),null==j&&(k=o.display,j="none"===k?"":k)),o.display="inline-block")),c.overflow&&(o.overflow="hidden",m.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]})),i=!1;for(d in n)i||(q?"hidden"in q&&(p=q.hidden):q=V.access(a,"fxshow",{display:j}),f&&(q.hidden=!p),p&&ga([a],!0),m.done(function(){p||ga([a]),V.remove(a,"fxshow");for(d in n)r.style(a,d,n[d])})),i=db(p?q[d]:0,d,m),d in q||(q[d]=i.start,p&&(i.end=i.start,i.start=0))}}function fb(a,b){var c,d,e,f,g;for(c in a)if(d=r.camelCase(c),e=b[d],f=a[c],r.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=r.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function gb(a,b,c){var d,e,f=0,g=gb.prefilters.length,h=r.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Ya||bb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;g<i;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),f<1&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:r.extend({},b),opts:r.extend(!0,{specialEasing:{},easing:r.easing._default},c),originalProperties:b,originalOptions:c,startTime:Ya||bb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=r.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;c<d;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(fb(k,j.opts.specialEasing);f<g;f++)if(d=gb.prefilters[f].call(j,a,k,j.opts))return r.isFunction(d.stop)&&(r._queueHooks(j.elem,j.opts.queue).stop=r.proxy(d.stop,d)),d;return r.map(k,db,j),r.isFunction(j.opts.start)&&j.opts.start.call(a,j),r.fx.timer(r.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}r.Animation=r.extend(gb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return da(c.elem,a,_.exec(b),c),c}]},tweener:function(a,b){r.isFunction(a)?(b=a,a=["*"]):a=a.match(K);for(var c,d=0,e=a.length;d<e;d++)c=a[d],gb.tweeners[c]=gb.tweeners[c]||[],gb.tweeners[c].unshift(b)},prefilters:[eb],prefilter:function(a,b){b?gb.prefilters.unshift(a):gb.prefilters.push(a)}}),r.speed=function(a,b,c){var e=a&&"object"==typeof a?r.extend({},a):{complete:c||!c&&b||r.isFunction(a)&&a,duration:a,easing:c&&b||b&&!r.isFunction(b)&&b};return r.fx.off||d.hidden?e.duration=0:e.duration="number"==typeof e.duration?e.duration:e.duration in r.fx.speeds?r.fx.speeds[e.duration]:r.fx.speeds._default,null!=e.queue&&e.queue!==!0||(e.queue="fx"),e.old=e.complete,e.complete=function(){r.isFunction(e.old)&&e.old.call(this),e.queue&&r.dequeue(this,e.queue)},e},r.fn.extend({fadeTo:function(a,b,c,d){return this.filter(ba).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=r.isEmptyObject(a),f=r.speed(b,c,d),g=function(){var b=gb(this,r.extend({},a),f);(e||V.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=r.timers,g=V.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&_a.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||r.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=V.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=r.timers,g=d?d.length:0;for(c.finish=!0,r.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;b<g;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),r.each(["toggle","show","hide"],function(a,b){var c=r.fn[b];r.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(cb(b,!0),a,d,e)}}),r.each({slideDown:cb("show"),slideUp:cb("hide"),slideToggle:cb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){r.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),r.timers=[],r.fx.tick=function(){var a,b=0,c=r.timers;for(Ya=r.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||r.fx.stop(),Ya=void 0},r.fx.timer=function(a){r.timers.push(a),a()?r.fx.start():r.timers.pop()},r.fx.interval=13,r.fx.start=function(){Za||(Za=a.requestAnimationFrame?a.requestAnimationFrame(ab):a.setInterval(r.fx.tick,r.fx.interval))},r.fx.stop=function(){a.cancelAnimationFrame?a.cancelAnimationFrame(Za):a.clearInterval(Za),Za=null},r.fx.speeds={slow:600,fast:200,_default:400},r.fn.delay=function(b,c){return b=r.fx?r.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",o.checkOn=""!==a.value,o.optSelected=c.selected,a=d.createElement("input"),a.value="t",a.type="radio",o.radioValue="t"===a.value}();var hb,ib=r.expr.attrHandle;r.fn.extend({attr:function(a,b){return S(this,r.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?hb:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&r.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(K);
+if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),hb={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=ib[b]||r.find.attr;ib[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=ib[g],ib[g]=e,e=null!=c(a,b,d)?g:null,ib[g]=f),e}});var jb=/^(?:input|select|textarea|button)$/i,kb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return S(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):jb.test(a.nodeName)||kb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});var lb=/[\t\r\n\f]/g;function mb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,mb(this)))});if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,mb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,mb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(K)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=mb(this),b&&V.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":V.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+mb(c)+" ").replace(lb," ").indexOf(b)>-1)return!0;return!1}});var nb=/\r/g,ob=/[\x20\t\r\n\f]+/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":r.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(nb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:r.trim(r.text(a)).replace(ob," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type,g=f?null:[],h=f?e+1:d.length,i=e<0?h:f?e:0;i<h;i++)if(c=d[i],(c.selected||i===e)&&!c.disabled&&(!c.parentNode.disabled||!r.nodeName(c.parentNode,"optgroup"))){if(b=r(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=r.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=r.inArray(r.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(r.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var pb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!pb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,pb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(V.get(h,"events")||{})[b.type]&&V.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&T(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!T(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=V.access(d,b);e||d.addEventListener(a,c,!0),V.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=V.access(d,b)-1;e?V.access(d,b,e):(d.removeEventListener(a,c,!0),V.remove(d,b))}}});var qb=a.location,rb=r.now(),sb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var tb=/\[\]$/,ub=/\r?\n/g,vb=/^(?:submit|button|image|reset|file)$/i,wb=/^(?:input|select|textarea|keygen)/i;function xb(a,b,c,d){var e;if(r.isArray(b))r.each(b,function(b,e){c||tb.test(a)?d(a,e):xb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)xb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(r.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)xb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&wb.test(this.nodeName)&&!vb.test(a)&&(this.checked||!ha.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:r.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ub,"\r\n")}}):{name:b.name,value:c.replace(ub,"\r\n")}}).get()}});var yb=/%20/g,zb=/#.*$/,Ab=/([?&])_=[^&]*/,Bb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Cb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Db=/^(?:GET|HEAD)$/,Eb=/^\/\//,Fb={},Gb={},Hb="*/".concat("*"),Ib=d.createElement("a");Ib.href=qb.href;function Jb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(K)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Kb(a,b,c,d){var e={},f=a===Gb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Lb(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Mb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Nb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:qb.href,type:"GET",isLocal:Cb.test(qb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Hb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Lb(Lb(a,r.ajaxSettings),b):Lb(r.ajaxSettings,a)},ajaxPrefilter:Jb(Fb),ajaxTransport:Jb(Gb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Bb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||qb.href)+"").replace(Eb,qb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(K)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Ib.protocol+"//"+Ib.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Kb(Fb,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Db.test(o.type),f=o.url.replace(zb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(yb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(sb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Ab,""),n=(sb.test(f)?"&":"?")+"_="+rb++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Hb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Kb(Gb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Mb(o,y,d)),v=Nb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Ob={0:200,1223:204},Pb=r.ajaxSettings.xhr();o.cors=!!Pb&&"withCredentials"in Pb,o.ajax=Pb=!!Pb,r.ajaxTransport(function(b){var c,d;if(o.cors||Pb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Ob[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r("<script>").prop({charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&f("error"===a.type?404:200,a.type)}),d.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Qb=[],Rb=/(=)\?(?=&|$)|\?\?/;r.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Qb.pop()||r.expando+"_"+rb++;return this[a]=!0,a}}),r.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Rb.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Rb.test(b.data)&&"data");if(h||"jsonp"===b.dataTypes[0])return e=b.jsonpCallback=r.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Rb,"$1"+e):b.jsonp!==!1&&(b.url+=(sb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||r.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?r(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Qb.push(e)),g&&r.isFunction(f)&&f(g[0]),g=f=void 0}),"script"}),o.createHTMLDocument=function(){var a=d.implementation.createHTMLDocument("").body;return a.innerHTML="<form></form><form></form>",2===a.childNodes.length}(),r.parseHTML=function(a,b,c){if("string"!=typeof a)return[];"boolean"==typeof b&&(c=b,b=!1);var e,f,g;return b||(o.createHTMLDocument?(b=d.implementation.createHTMLDocument(""),e=b.createElement("base"),e.href=d.location.href,b.head.appendChild(e)):b=d),f=B.exec(a),g=!c&&[],f?[b.createElement(f[1])]:(f=oa([a],b,g),g&&g.length&&r(g).remove(),r.merge([],f.childNodes))},r.fn.load=function(a,b,c){var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=r.trim(a.slice(h)),a=a.slice(0,h)),r.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&r.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?r("<div>").append(r.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},r.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){r.fn[b]=function(a){return this.on(b,a)}}),r.expr.pseudos.animated=function(a){return r.grep(r.timers,function(b){return a===b.elem}).length};function Sb(a){return r.isWindow(a)?a:9===a.nodeType&&a.defaultView}r.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=r.css(a,"position"),l=r(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=r.css(a,"top"),i=r.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),r.isFunction(b)&&(b=b.call(a,c,r.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},r.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){r.offset.setOffset(this,a,b)});var b,c,d,e,f=this[0];if(f)return f.getClientRects().length?(d=f.getBoundingClientRect(),d.width||d.height?(e=f.ownerDocument,c=Sb(e),b=e.documentElement,{top:d.top+c.pageYOffset-b.clientTop,left:d.left+c.pageXOffset-b.clientLeft}):d):{top:0,left:0}},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===r.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),r.nodeName(a[0],"html")||(d=a.offset()),d={top:d.top+r.css(a[0],"borderTopWidth",!0),left:d.left+r.css(a[0],"borderLeftWidth",!0)}),{top:b.top-d.top-r.css(c,"marginTop",!0),left:b.left-d.left-r.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===r.css(a,"position"))a=a.offsetParent;return a||pa})}}),r.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;r.fn[a]=function(d){return S(this,function(a,d,e){var f=Sb(a);return void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),r.each(["top","left"],function(a,b){r.cssHooks[b]=Na(o.pixelPosition,function(a,c){if(c)return c=Ma(a,b),Ka.test(c)?r(a).position()[b]+"px":c})}),r.each({Height:"height",Width:"width"},function(a,b){r.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){r.fn[d]=function(e,f){var g=arguments.length&&(c||"boolean"!=typeof e),h=c||(e===!0||f===!0?"margin":"border");return S(this,function(b,c,e){var f;return r.isWindow(b)?0===d.indexOf("outer")?b["inner"+a]:b.document.documentElement["client"+a]:9===b.nodeType?(f=b.documentElement,Math.max(b.body["scroll"+a],f["scroll"+a],b.body["offset"+a],f["offset"+a],f["client"+a])):void 0===e?r.css(b,c,h):r.style(b,c,e,h)},b,g?e:void 0,g)}})}),r.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),r.parseJSON=JSON.parse,"function"==typeof define&&define.amd&&define("jquery",[],function(){return r});var Tb=a.jQuery,Ub=a.$;return r.noConflict=function(b){return a.$===r&&(a.$=Ub),b&&a.jQuery===r&&(a.jQuery=Tb),r},b||(a.jQuery=a.$=r),r});
diff --git a/sphinx/themes/basic/static/minus.png b/sphinx/themes/basic/static/minus.png
index 0f22b16b0..d96755fda 100644
--- a/sphinx/themes/basic/static/minus.png
+++ b/sphinx/themes/basic/static/minus.png
Binary files differ
diff --git a/sphinx/themes/basic/static/plus.png b/sphinx/themes/basic/static/plus.png
index 0cfe084cf..7107cec93 100644
--- a/sphinx/themes/basic/static/plus.png
+++ b/sphinx/themes/basic/static/plus.png
Binary files differ
diff --git a/sphinx/themes/basic/static/searchtools.js_t b/sphinx/themes/basic/static/searchtools.js_t
index 8a150b272..cf899ef85 100644
--- a/sphinx/themes/basic/static/searchtools.js_t
+++ b/sphinx/themes/basic/static/searchtools.js_t
@@ -159,6 +159,10 @@ var Search = {
}
// stem the word
var word = stemmer.stemWord(tmp[i].toLowerCase());
+ // prevent stemmer from cutting word smaller than two chars
+ if(word.length < 3 && tmp[i].length >= 3) {
+ word = tmp[i];
+ }
var toAppend;
// select the correct list
if (word[0] == '-') {
@@ -256,7 +260,8 @@ var Search = {
displayNextItem();
});
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
- $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[0] + '.txt',
+ var suffix = DOCUMENTATION_OPTIONS.SOURCELINK_SUFFIX;
+ $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[5] + (item[5].endsWith(suffix) ? '' : suffix),
dataType: "text",
complete: function(jqxhr, textstatus) {
var data = jqxhr.responseText;
@@ -295,6 +300,7 @@ var Search = {
*/
performObjectSearch : function(object, otherterms) {
var filenames = this._index.filenames;
+ var docnames = this._index.docnames;
var objects = this._index.objects;
var objnames = this._index.objnames;
var titles = this._index.titles;
@@ -348,7 +354,7 @@ var Search = {
} else {
score += Scorer.objPrioDefault;
}
- results.push([filenames[match[0]], fullname, '#'+anchor, descr, score]);
+ results.push([docnames[match[0]], fullname, '#'+anchor, descr, score, filenames[match[0]]]);
}
}
}
@@ -360,6 +366,7 @@ var Search = {
* search for full-text terms in the index
*/
performTermsSearch : function(searchterms, excluded, terms, titleterms) {
+ var docnames = this._index.docnames;
var filenames = this._index.filenames;
var titles = this._index.titles;
@@ -434,7 +441,7 @@ var Search = {
// select one (max) score for the file.
// for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
- results.push([filenames[file], titles[file], '', null, score]);
+ results.push([docnames[file], titles[file], '', null, score, filenames[file]]);
}
}
return results;
diff --git a/sphinx/themes/basic/static/up-pressed.png b/sphinx/themes/basic/static/up-pressed.png
index 99e721096..acee3b68e 100644
--- a/sphinx/themes/basic/static/up-pressed.png
+++ b/sphinx/themes/basic/static/up-pressed.png
Binary files differ
diff --git a/sphinx/themes/basic/static/up.png b/sphinx/themes/basic/static/up.png
index 26de002e8..2a940a7da 100644
--- a/sphinx/themes/basic/static/up.png
+++ b/sphinx/themes/basic/static/up.png
Binary files differ
diff --git a/sphinx/themes/bizstyle/static/background_b01.png b/sphinx/themes/bizstyle/static/background_b01.png
index d262745b4..353f26dde 100644
--- a/sphinx/themes/bizstyle/static/background_b01.png
+++ b/sphinx/themes/bizstyle/static/background_b01.png
Binary files differ
diff --git a/sphinx/themes/epub/layout.html b/sphinx/themes/epub/layout.html
index bdbcec21d..541fcdba5 100644
--- a/sphinx/themes/epub/layout.html
+++ b/sphinx/themes/epub/layout.html
@@ -10,8 +10,7 @@
{%- extends "basic/layout.html" %}
{%- block doctype -%}
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
- "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+{{ doctype }}
{%- endblock -%}
{# add only basic navigation links #}
{% block sidebar1 %}{% endblock %}
diff --git a/sphinx/themes/epub/static/epub.css b/sphinx/themes/epub/static/epub.css
index 84db952c4..bfa1eaebc 100644
--- a/sphinx/themes/epub/static/epub.css
+++ b/sphinx/themes/epub/static/epub.css
@@ -184,10 +184,6 @@ div.body td {
text-align: left;
}
-.field-list ul {
- padding-left: 100%;
-}
-
.first {
margin-top: 0 !important;
}
@@ -286,10 +282,6 @@ table.docutils td, table.docutils th {
border-bottom: 1px solid #aaa;
}
-table.field-list td, table.field-list th {
- border: 0 !important;
-}
-
table.footnote td, table.footnote th {
border: 0 !important;
}
@@ -317,6 +309,21 @@ div.figure p.caption span.caption-number {
div.figure p.caption span.caption-text {
}
+/* -- field list styles ----------------------------------------------------- */
+
+table.field-list td, table.field-list th {
+ border: 0 !important;
+}
+
+.field-list ul {
+ margin: 0;
+ padding-left: 1em;
+}
+
+.field-list p {
+ margin: 0;
+}
+
/* -- other body styles ----------------------------------------------------- */
ol.arabic {
@@ -366,15 +373,6 @@ dl.glossary dt {
font-size: 110%;
}
-.field-list ul {
- margin: 0;
- padding-left: 1em;
-}
-
-.field-list p {
- margin: 0;
-}
-
.optional {
font-size: 130%;
}
diff --git a/sphinx/themes/haiku/static/alert_info_32.png b/sphinx/themes/haiku/static/alert_info_32.png
index 05b4fe898..ea4d1baf7 100644
--- a/sphinx/themes/haiku/static/alert_info_32.png
+++ b/sphinx/themes/haiku/static/alert_info_32.png
Binary files differ
diff --git a/sphinx/themes/haiku/static/alert_warning_32.png b/sphinx/themes/haiku/static/alert_warning_32.png
index f13611cde..a687c3dca 100644
--- a/sphinx/themes/haiku/static/alert_warning_32.png
+++ b/sphinx/themes/haiku/static/alert_warning_32.png
Binary files differ
diff --git a/sphinx/themes/haiku/static/bg-page.png b/sphinx/themes/haiku/static/bg-page.png
index 0103ee1a7..fe0a6dc89 100644
--- a/sphinx/themes/haiku/static/bg-page.png
+++ b/sphinx/themes/haiku/static/bg-page.png
Binary files differ
diff --git a/sphinx/themes/haiku/static/bullet_orange.png b/sphinx/themes/haiku/static/bullet_orange.png
index ad5d02f34..1cb8097ce 100644
--- a/sphinx/themes/haiku/static/bullet_orange.png
+++ b/sphinx/themes/haiku/static/bullet_orange.png
Binary files differ
diff --git a/sphinx/themes/nonav/layout.html b/sphinx/themes/nonav/layout.html
new file mode 100644
index 000000000..256c2d5b2
--- /dev/null
+++ b/sphinx/themes/nonav/layout.html
@@ -0,0 +1,23 @@
+{#
+ nonav/layout.html
+ ~~~~~~~~~~~~~~~~
+
+ Sphinx layout template for the any help system theme.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+#}
+{%- extends "basic/layout.html" %}
+
+{%- block doctype -%}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+{%- endblock -%}
+{# add only basic navigation links #}
+{% block sidebar1 %}{% endblock %}
+{% block sidebar2 %}{% endblock %}
+{% block relbar1 %}{% endblock %}
+{% block relbar2 %}{% endblock %}
+{% block linktags %}{% endblock %}
+{% block footer %}{% endblock %}
+
diff --git a/sphinx/themes/nonav/static/nonav.css b/sphinx/themes/nonav/static/nonav.css
new file mode 100644
index 000000000..61ece23b3
--- /dev/null
+++ b/sphinx/themes/nonav/static/nonav.css
@@ -0,0 +1,568 @@
+/*
+ * nonav.css
+ * ~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- nonav theme.
+ *
+ * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+/* -- main layout ----------------------------------------------------------- */
+
+div.clearer {
+ clear: both;
+}
+
+a:link, a:visited {
+ color: #3333ff;
+ text-decoration: underline;
+}
+
+img {
+ border: 0;
+ max-width: 100%;
+}
+
+/* -- relbar ---------------------------------------------------------------- */
+
+div.related {
+ width: 100%;
+ font-family: sans-serif;
+ font-size: 90%;
+}
+
+div.related h3 {
+ display: none;
+}
+
+div.related ul {
+ margin: 0;
+ padding: 0 0 0 10px;
+ list-style: none;
+}
+
+div.related li {
+ display: inline;
+}
+
+div.related li.right {
+ float: right;
+ margin-right: 5px;
+}
+
+/* -- sidebar --------------------------------------------------------------- */
+
+div.sphinxsidebarwrapper {
+ padding: 10px 5px 0 10px;
+}
+
+div.sphinxsidebar {
+ float: left;
+ width: 230px;
+ margin-left: -100%;
+ font-size: 90%;
+}
+
+div.sphinxsidebar ul {
+ list-style: none;
+}
+
+div.sphinxsidebar ul ul,
+div.sphinxsidebar ul.want-points {
+ margin-left: 20px;
+ list-style: square;
+}
+
+div.sphinxsidebar ul ul {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+div.sphinxsidebar form {
+ margin-top: 10px;
+}
+
+div.sphinxsidebar input {
+ border: 1px solid #98dbcc;
+ font-family: sans-serif;
+ font-size: 100%;
+}
+
+img {
+ border: 0;
+ max-width: 100%;
+}
+
+/* -- search page ----------------------------------------------------------- */
+
+ul.search {
+ margin: 10px 0 0 20px;
+ padding: 0;
+}
+
+ul.search li {
+ padding: 5px 0 5px 20px;
+ background-image: url(file.png);
+ background-repeat: no-repeat;
+ background-position: 0 7px;
+}
+
+ul.search li a {
+ font-weight: bold;
+}
+
+ul.search li div.context {
+ color: #888;
+ margin: 2px 0 0 30px;
+ text-align: left;
+}
+
+ul.keywordmatches li.goodmatch a {
+ font-weight: bold;
+}
+
+/* -- index page ------------------------------------------------------------ */
+
+table.contentstable {
+ width: 90%;
+}
+
+table.contentstable p.biglink {
+ line-height: 150%;
+}
+
+a.biglink {
+ font-size: 130%;
+}
+
+span.linkdescr {
+ font-style: italic;
+ padding-top: 5px;
+ font-size: 90%;
+}
+
+/* -- general index --------------------------------------------------------- */
+
+table.indextable td {
+ text-align: left;
+ vertical-align: top;
+}
+
+table.indextable dl, table.indextable dd {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+table.indextable tr.pcap {
+ height: 10px;
+}
+
+table.indextable tr.cap {
+ margin-top: 10px;
+ background-color: #f2f2f2;
+}
+
+img.toggler {
+ margin-right: 3px;
+ margin-top: 3px;
+ cursor: pointer;
+}
+
+/* -- general body styles --------------------------------------------------- */
+
+a.headerlink {
+ visibility: hidden;
+}
+
+div.body p.caption {
+ text-align: inherit;
+}
+
+div.body td {
+ text-align: left;
+}
+
+.first {
+ margin-top: 0 !important;
+}
+
+p.rubric {
+ margin-top: 30px;
+ font-weight: bold;
+}
+
+.align-left {
+ text-align: left;
+}
+
+.align-center {
+ text-align: center;
+}
+
+.align-right {
+ text-align: right;
+}
+
+/* -- sidebars -------------------------------------------------------------- */
+
+div.sidebar {
+ margin: 0 0 0.5em 1em;
+ border: 1px solid #ddb;
+ padding: 7px 7px 0 7px;
+ background-color: #ffe;
+ width: 40%;
+ float: right;
+}
+
+p.sidebar-title {
+ font-weight: bold;
+}
+
+/* -- topics ---------------------------------------------------------------- */
+
+div.topic {
+ border: 1px solid #ccc;
+ padding: 7px 7px 0 7px;
+ margin: 10px 0 10px 0;
+}
+
+p.topic-title {
+ font-size: 110%;
+ font-weight: bold;
+ margin-top: 10px;
+}
+
+/* -- admonitions ----------------------------------------------------------- */
+
+div.admonition {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 7px;
+}
+
+div.admonition dt {
+ font-weight: bold;
+}
+
+div.admonition dl {
+ margin-bottom: 0;
+}
+
+p.admonition-title {
+ margin: 0px 10px 5px 0px;
+ font-weight: bold;
+}
+
+div.body p.centered {
+ text-align: center;
+ margin-top: 25px;
+}
+
+/* -- tables ---------------------------------------------------------------- */
+
+table.docutils {
+ border: 0;
+ border-collapse: collapse;
+}
+
+table caption span.caption-number {
+ font-style: italic;
+}
+
+table caption span.caption-text {
+}
+
+table.docutils td, table.docutils th {
+ padding: 1px 8px 1px 5px;
+ border-top: 0;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 1px solid #aaa;
+}
+
+table.footnote td, table.footnote th {
+ border: 0 !important;
+}
+
+th {
+ text-align: left;
+ padding-right: 5px;
+}
+
+table.citation {
+ border-left: solid 1px gray;
+ margin-left: 1px;
+}
+
+table.citation td {
+ border-bottom: none;
+}
+
+/* -- figures --------------------------------------------------------------- */
+
+div.figure p.caption span.caption-number {
+ font-style: italic;
+}
+
+div.figure p.caption span.caption-text {
+}
+
+/* -- field list styles ----------------------------------------------------- */
+
+table.field-list td, table.field-list th {
+ border: 0 !important;
+}
+
+.field-list ul {
+ margin: 0;
+ padding-left: 1em;
+}
+
+.field-list p {
+ margin: 0;
+}
+
+/* -- other body styles ----------------------------------------------------- */
+
+ol.arabic {
+ list-style: decimal;
+}
+
+ol.loweralpha {
+ list-style: lower-alpha;
+}
+
+ol.upperalpha {
+ list-style: upper-alpha;
+}
+
+ol.lowerroman {
+ list-style: lower-roman;
+}
+
+ol.upperroman {
+ list-style: upper-roman;
+}
+
+dl {
+ margin-bottom: 15px;
+}
+
+dd p {
+ margin-top: 0px;
+}
+
+dd ul, dd table {
+ margin-bottom: 10px;
+}
+
+dd {
+ margin-top: 3px;
+ margin-bottom: 10px;
+ margin-left: 30px;
+}
+
+dt:target, .highlighted {
+ background-color: #ddd;
+}
+
+dl.glossary dt {
+ font-weight: bold;
+ font-size: 110%;
+}
+
+.optional {
+ font-size: 130%;
+}
+
+.sig-paren {
+ font-size: larger;
+}
+
+.versionmodified {
+ font-style: italic;
+}
+
+.system-message {
+ background-color: #fda;
+ padding: 5px;
+ border: 3px solid red;
+}
+
+.footnote:target {
+ background-color: #dddddd;
+}
+
+.line-block {
+ display: block;
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+
+.line-block .line-block {
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 1.5em;
+}
+
+.guilabel, .menuselection {
+ font-style: italic;
+}
+
+.accelerator {
+ text-decoration: underline;
+}
+
+.classifier {
+ font-style: oblique;
+}
+
+abbr, acronym {
+ border-bottom: dotted 1px;
+ cursor: help;
+}
+
+/* -- code displays --------------------------------------------------------- */
+
+pre {
+ font-family: monospace;
+ overflow: auto;
+ overflow-y: hidden;
+}
+
+td.linenos pre {
+ padding: 5px 0px;
+ border: 0;
+ background-color: transparent;
+ color: #aaa;
+}
+
+table.highlighttable {
+ margin-left: 0.5em;
+}
+
+table.highlighttable td {
+ padding: 0 0.5em 0 0.5em;
+}
+
+code {
+ font-family: monospace;
+}
+
+div.code-block-caption span.caption-number {
+ padding: 0.1em 0.3em;
+ font-style: italic;
+}
+
+div.code-block-caption span.caption-text {
+}
+
+div.literal-block-wrapper {
+ padding: 1em 1em 0;
+}
+
+div.literal-block-wrapper div.highlight {
+ margin: 0;
+}
+
+code.descname {
+ background-color: transparent;
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+code.descclassname {
+ background-color: transparent;
+}
+
+code.xref, a code {
+ background-color: transparent;
+ font-weight: bold;
+}
+
+h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
+ background-color: transparent;
+}
+
+/* -- math display ---------------------------------------------------------- */
+
+img.math {
+ vertical-align: middle;
+}
+
+div.body div.math p {
+ text-align: center;
+}
+
+span.eqno {
+ float: right;
+}
+
+/* -- special divs --------------------------------------------------------- */
+
+div.quotebar {
+ background-color: #e3eff1;
+ max-width: 250px;
+ float: right;
+ font-family: sans-serif;
+ padding: 7px 7px;
+ border: 1px solid #ccc;
+}
+div.footer {
+ background-color: #e3eff1;
+ padding: 3px 8px 3px 0;
+ clear: both;
+ font-family: sans-serif;
+ font-size: 80%;
+ text-align: right;
+}
+
+div.footer a {
+ text-decoration: underline;
+}
+
+/* -- link-target ----------------------------------------------------------- */
+
+.link-target {
+ font-size: 80%;
+}
+
+table .link-target {
+ /* Do not show links in tables, there is not enough space */
+ display: none;
+}
+
+/* -- font-face ------------------------------------------------------------- */
+
+/*
+@font-face {
+ font-family: "LiberationNarrow";
+ font-style: normal;
+ font-weight: normal;
+ src: url("res:///Data/fonts/LiberationNarrow-Regular.otf")
+ format("opentype");
+}
+@font-face {
+ font-family: "LiberationNarrow";
+ font-style: oblique, italic;
+ font-weight: normal;
+ src: url("res:///Data/fonts/LiberationNarrow-Italic.otf")
+ format("opentype");
+}
+@font-face {
+ font-family: "LiberationNarrow";
+ font-style: normal;
+ font-weight: bold;
+ src: url("res:///Data/fonts/LiberationNarrow-Bold.otf")
+ format("opentype");
+}
+@font-face {
+ font-family: "LiberationNarrow";
+ font-style: oblique, italic;
+ font-weight: bold;
+ src: url("res:///Data/fonts/LiberationNarrow-BoldItalic.otf")
+ format("opentype");
+}
+*/
diff --git a/sphinx/themes/nonav/theme.conf b/sphinx/themes/nonav/theme.conf
new file mode 100644
index 000000000..d4799c75a
--- /dev/null
+++ b/sphinx/themes/nonav/theme.conf
@@ -0,0 +1,8 @@
+[theme]
+inherit = basic
+stylesheet = nonav.css
+pygments_style = none
+
+[options]
+relbar1 = true
+footer = true
diff --git a/sphinx/themes/pyramid/static/dialog-note.png b/sphinx/themes/pyramid/static/dialog-note.png
index 708682114..5a6336d11 100644
--- a/sphinx/themes/pyramid/static/dialog-note.png
+++ b/sphinx/themes/pyramid/static/dialog-note.png
Binary files differ
diff --git a/sphinx/themes/pyramid/static/dialog-seealso.png b/sphinx/themes/pyramid/static/dialog-seealso.png
index a27a0fcba..97553a8b7 100644
--- a/sphinx/themes/pyramid/static/dialog-seealso.png
+++ b/sphinx/themes/pyramid/static/dialog-seealso.png
Binary files differ
diff --git a/sphinx/themes/pyramid/static/dialog-todo.png b/sphinx/themes/pyramid/static/dialog-todo.png
index 9caa91e8a..cfbc28088 100644
--- a/sphinx/themes/pyramid/static/dialog-todo.png
+++ b/sphinx/themes/pyramid/static/dialog-todo.png
Binary files differ
diff --git a/sphinx/themes/pyramid/static/dialog-topic.png b/sphinx/themes/pyramid/static/dialog-topic.png
index 2ac57475c..a75afeaaf 100644
--- a/sphinx/themes/pyramid/static/dialog-topic.png
+++ b/sphinx/themes/pyramid/static/dialog-topic.png
Binary files differ
diff --git a/sphinx/themes/pyramid/static/dialog-warning.png b/sphinx/themes/pyramid/static/dialog-warning.png
index 4f598b12b..8bb7d8d35 100644
--- a/sphinx/themes/pyramid/static/dialog-warning.png
+++ b/sphinx/themes/pyramid/static/dialog-warning.png
Binary files differ
diff --git a/sphinx/themes/pyramid/static/headerbg.png b/sphinx/themes/pyramid/static/headerbg.png
index 0596f2020..e1051af48 100644
--- a/sphinx/themes/pyramid/static/headerbg.png
+++ b/sphinx/themes/pyramid/static/headerbg.png
Binary files differ
diff --git a/sphinx/themes/pyramid/static/middlebg.png b/sphinx/themes/pyramid/static/middlebg.png
index b3a89f4e5..5ee55db25 100644
--- a/sphinx/themes/pyramid/static/middlebg.png
+++ b/sphinx/themes/pyramid/static/middlebg.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/darkmetal.png b/sphinx/themes/scrolls/static/darkmetal.png
index 3ed486d5c..49c82f301 100644
--- a/sphinx/themes/scrolls/static/darkmetal.png
+++ b/sphinx/themes/scrolls/static/darkmetal.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/headerbg.png b/sphinx/themes/scrolls/static/headerbg.png
index 0c5b3657c..ef15cc09c 100644
--- a/sphinx/themes/scrolls/static/headerbg.png
+++ b/sphinx/themes/scrolls/static/headerbg.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/logo.png b/sphinx/themes/scrolls/static/logo.png
index 3dc573e0f..354aded6b 100644
--- a/sphinx/themes/scrolls/static/logo.png
+++ b/sphinx/themes/scrolls/static/logo.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/metal.png b/sphinx/themes/scrolls/static/metal.png
index e51010b5f..c29cd9eca 100644
--- a/sphinx/themes/scrolls/static/metal.png
+++ b/sphinx/themes/scrolls/static/metal.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/navigation.png b/sphinx/themes/scrolls/static/navigation.png
index 5be5b3183..89c447a29 100644
--- a/sphinx/themes/scrolls/static/navigation.png
+++ b/sphinx/themes/scrolls/static/navigation.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/watermark.png b/sphinx/themes/scrolls/static/watermark.png
index 903a96edb..d71dc4bbe 100644
--- a/sphinx/themes/scrolls/static/watermark.png
+++ b/sphinx/themes/scrolls/static/watermark.png
Binary files differ
diff --git a/sphinx/themes/scrolls/static/watermark_blur.png b/sphinx/themes/scrolls/static/watermark_blur.png
index 022690062..9fc0b6d31 100644
--- a/sphinx/themes/scrolls/static/watermark_blur.png
+++ b/sphinx/themes/scrolls/static/watermark_blur.png
Binary files differ
diff --git a/sphinx/themes/sphinxdoc/static/contents.png b/sphinx/themes/sphinxdoc/static/contents.png
index 7fb82154a..6c59aa1f9 100644
--- a/sphinx/themes/sphinxdoc/static/contents.png
+++ b/sphinx/themes/sphinxdoc/static/contents.png
Binary files differ
diff --git a/sphinx/themes/sphinxdoc/static/navigation.png b/sphinx/themes/sphinxdoc/static/navigation.png
index 1081dc143..fda6cd29e 100644
--- a/sphinx/themes/sphinxdoc/static/navigation.png
+++ b/sphinx/themes/sphinxdoc/static/navigation.png
Binary files differ
diff --git a/sphinx/theming.py b/sphinx/theming.py
index 539184115..42e4448db 100644
--- a/sphinx/theming.py
+++ b/sphinx/theming.py
@@ -133,9 +133,8 @@ class Theme(object):
dirname = path.dirname(name)
if not path.isdir(path.join(self.themedir, dirname)):
os.makedirs(path.join(self.themedir, dirname))
- fp = open(path.join(self.themedir, name), 'wb')
- fp.write(tinfo.read(name))
- fp.close()
+ with open(path.join(self.themedir, name), 'wb') as fp:
+ fp.write(tinfo.read(name))
self.themeconf = configparser.RawConfigParser()
self.themeconf.read(path.join(self.themedir, THEMECONF))
diff --git a/sphinx/transforms.py b/sphinx/transforms.py
index abeab7dab..cb4a5779b 100644
--- a/sphinx/transforms.py
+++ b/sphinx/transforms.py
@@ -170,6 +170,24 @@ class ApplySourceWorkaround(Transform):
apply_source_workaround(n)
+class AutoIndexUpgrader(Transform):
+ """
+ Detect old style; 4 column based indices and automatically upgrade to new style.
+ """
+ default_priority = 210
+
+ def apply(self):
+ env = self.document.settings.env
+ for node in self.document.traverse(addnodes.index):
+ if 'entries' in node and any(len(entry) == 4 for entry in node['entries']):
+ msg = ('4 column based index found. '
+ 'It might be a bug of extensions you use: %r' % node['entries'])
+ env.warn_node(msg, node)
+ for i, entry in enumerate(node['entries']):
+ if len(entry) == 4:
+ node['entries'][i] = entry + (None,)
+
+
class ExtraTranslatableNodes(Transform):
"""
make nodes translatable
diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py
index 0c823fb1a..a0dababc8 100644
--- a/sphinx/util/__init__.py
+++ b/sphinx/util/__init__.py
@@ -18,7 +18,7 @@ import posixpath
import traceback
import unicodedata
from os import path
-from codecs import open, BOM_UTF8
+from codecs import BOM_UTF8
from collections import deque
from six import iteritems, text_type, binary_type
@@ -32,6 +32,7 @@ import jinja2
import sphinx
from sphinx.errors import PycodeError, SphinxParallelError, ExtensionError
from sphinx.util.console import strip_colors
+from sphinx.util.fileutil import copy_asset_file
from sphinx.util.osutil import fs_encoding
# import other utilities; partly for backwards compatibility, so don't
@@ -148,7 +149,7 @@ class FilenameUniqDict(dict):
def copy_static_entry(source, targetdir, builder, context={},
exclude_matchers=(), level=0):
- """Copy a HTML builder static_path entry from source to targetdir.
+ """[DEPRECATED] Copy a HTML builder static_path entry from source to targetdir.
Handles all possible cases of files, directories and subdirectories.
"""
@@ -158,16 +159,7 @@ def copy_static_entry(source, targetdir, builder, context={},
if matcher(relpath):
return
if path.isfile(source):
- target = path.join(targetdir, path.basename(source))
- if source.lower().endswith('_t') and builder.templates:
- # templated!
- fsrc = open(source, 'r', encoding='utf-8')
- fdst = open(target[:-2], 'w', encoding='utf-8')
- fdst.write(builder.templates.render_string(fsrc.read(), context))
- fsrc.close()
- fdst.close()
- else:
- copyfile(source, target)
+ copy_asset_file(source, targetdir, context, builder.templates)
elif path.isdir(source):
if not path.isdir(targetdir):
os.mkdir(targetdir)
@@ -181,37 +173,6 @@ def copy_static_entry(source, targetdir, builder, context={},
builder, context, level=level+1,
exclude_matchers=exclude_matchers)
-
-def copy_extra_entry(source, targetdir, exclude_matchers=()):
- """Copy a HTML builder extra_path entry from source to targetdir.
-
- Handles all possible cases of files, directories and subdirectories.
- """
- def excluded(path):
- relpath = relative_path(os.path.dirname(source), path)
- return any(matcher(relpath) for matcher in exclude_matchers)
-
- def copy_extra_file(source_, targetdir_):
- if not excluded(source_):
- target = path.join(targetdir_, os.path.basename(source_))
- copyfile(source_, target)
-
- if os.path.isfile(source):
- copy_extra_file(source, targetdir)
- return
-
- for root, dirs, files in os.walk(source):
- reltargetdir = os.path.join(targetdir, relative_path(source, root))
- for dir in dirs[:]:
- if excluded(os.path.join(root, dir)):
- dirs.remove(dir)
- else:
- target = os.path.join(reltargetdir, dir)
- if not path.exists(target):
- os.mkdir(target)
- for file in files:
- copy_extra_file(os.path.join(root, file), reltargetdir)
-
_DEBUG_HEADER = '''\
# Sphinx version: %s
# Python version: %s (%s)
diff --git a/sphinx/util/docfields.py b/sphinx/util/docfields.py
index f4eb703ce..798645b46 100644
--- a/sphinx/util/docfields.py
+++ b/sphinx/util/docfields.py
@@ -62,6 +62,10 @@ class Field(object):
refnode += contnode or innernode(target, target)
return refnode
+ def make_xrefs(self, rolename, domain, target,
+ innernode=addnodes.literal_emphasis, contnode=None):
+ return [self.make_xref(rolename, domain, target, innernode, contnode)]
+
def make_entry(self, fieldarg, content):
return (fieldarg, content)
@@ -70,14 +74,15 @@ class Field(object):
fieldname = nodes.field_name('', self.label)
if fieldarg:
fieldname += nodes.Text(' ')
- fieldname += self.make_xref(self.rolename, domain,
- fieldarg, nodes.Text)
+ fieldname.extend(self.make_xrefs(self.rolename, domain,
+ fieldarg, nodes.Text))
+
if len(content) == 1 and (
isinstance(content[0], nodes.Text) or
(isinstance(content[0], nodes.inline) and len(content[0]) == 1 and
isinstance(content[0][0], nodes.Text))):
- content = [self.make_xref(self.bodyrolename, domain,
- content[0].astext(), contnode=content[0])]
+ content = self.make_xrefs(self.bodyrolename, domain,
+ content[0].astext(), contnode=content[0])
fieldbody = nodes.field_body('', nodes.paragraph('', '', *content))
return nodes.field('', fieldname, fieldbody)
@@ -108,14 +113,16 @@ class GroupedField(Field):
listnode = self.list_type()
for fieldarg, content in items:
par = nodes.paragraph()
- par += self.make_xref(self.rolename, domain, fieldarg,
- addnodes.literal_strong)
+ par.extend(self.make_xrefs(self.rolename, domain, fieldarg,
+ addnodes.literal_strong))
par += nodes.Text(' -- ')
par += content
listnode += nodes.list_item('', par)
+
if len(items) == 1 and self.can_collapse:
fieldbody = nodes.field_body('', listnode[0][0])
return nodes.field('', fieldname, fieldbody)
+
fieldbody = nodes.field_body('', listnode)
return nodes.field('', fieldname, fieldbody)
@@ -150,8 +157,8 @@ class TypedField(GroupedField):
def make_field(self, types, domain, items):
def handle_item(fieldarg, content):
par = nodes.paragraph()
- par += self.make_xref(self.rolename, domain, fieldarg,
- addnodes.literal_strong)
+ par.extend(self.make_xrefs(self.rolename, domain, fieldarg,
+ addnodes.literal_strong))
if fieldarg in types:
par += nodes.Text(' (')
# NOTE: using .pop() here to prevent a single type node to be
@@ -160,8 +167,8 @@ class TypedField(GroupedField):
fieldtype = types.pop(fieldarg)
if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text):
typename = u''.join(n.astext() for n in fieldtype)
- par += self.make_xref(self.typerolename, domain, typename,
- addnodes.literal_emphasis)
+ par.extend(self.make_xrefs(self.typerolename, domain, typename,
+ addnodes.literal_emphasis))
else:
par += fieldtype
par += nodes.Text(')')
diff --git a/sphinx/util/fileutil.py b/sphinx/util/fileutil.py
new file mode 100644
index 000000000..d11ae9f1b
--- /dev/null
+++ b/sphinx/util/fileutil.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.fileutil
+ ~~~~~~~~~~~~~~~~~~~~
+
+ File utility functions for Sphinx.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+import os
+import codecs
+import posixpath
+from docutils.utils import relative_path
+from sphinx.util.osutil import copyfile, ensuredir, walk
+
+
+def copy_asset_file(source, destination, context=None, renderer=None):
+ """Copy an asset file to destination.
+
+ On copying, it expands the template variables if context argument is given and
+ the asset is a template file.
+
+ :param source: The path to source file
+ :param destination: The path to destination file or directory
+ :param context: The template variables. If not given, template files are simply copied
+ :param renderer: The template engine. If not given, SphinxRenderer is used by default
+ """
+ if not os.path.exists(source):
+ return
+
+ if os.path.exists(destination) and os.path.isdir(destination):
+ # Use source filename if destination points a directory
+ destination = os.path.join(destination, os.path.basename(source))
+
+ if source.lower().endswith('_t') and context:
+ if renderer is None:
+ from sphinx.util.template import SphinxRenderer
+ renderer = SphinxRenderer()
+
+ with codecs.open(source, 'r', encoding='utf-8') as fsrc:
+ with codecs.open(destination[:-2], 'w', encoding='utf-8') as fdst:
+ fdst.write(renderer.render_string(fsrc.read(), context))
+ else:
+ copyfile(source, destination)
+
+
+def copy_asset(source, destination, excluded=lambda path: False, context=None, renderer=None):
+ """Copy asset files to destination recursively.
+
+ On copying, it expands the template variables if context argument is given and
+ the asset is a template file.
+
+ :param source: The path to source file or directory
+ :param destination: The path to destination directory
+ :param excluded: The matcher to determine the given path should be copied or not
+ :param context: The template variables. If not given, template files are simply copied
+ :param renderer: The template engine. If not given, SphinxRenderer is used by default
+ """
+ if not os.path.exists(source):
+ return
+
+ ensuredir(destination)
+ if os.path.isfile(source):
+ copy_asset_file(source, destination, context, renderer)
+ return
+
+ for root, dirs, files in walk(source):
+ reldir = relative_path(source, root)
+ for dir in dirs[:]:
+ if excluded(posixpath.join(reldir, dir)):
+ dirs.remove(dir)
+ else:
+ ensuredir(posixpath.join(destination, reldir, dir))
+
+ for filename in files:
+ if not excluded(posixpath.join(reldir, filename)):
+ copy_asset_file(posixpath.join(root, filename),
+ posixpath.join(destination, reldir),
+ context, renderer)
diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py
index 5dc2008c8..81ffe25c8 100644
--- a/sphinx/util/inspect.py
+++ b/sphinx/util/inspect.py
@@ -20,7 +20,7 @@ from sphinx.util import force_decode
# relatively import this module
inspect = __import__('inspect')
-memory_address_re = re.compile(r' at 0x[0-9a-f]{8,16}(?=>$)')
+memory_address_re = re.compile(r' at 0x[0-9a-f]{8,16}(?=>)')
if PY3:
@@ -108,10 +108,20 @@ def safe_getattr(obj, name, *defargs):
try:
return getattr(obj, name, *defargs)
except Exception:
+ # sometimes accessing a property raises an exception (e.g.
+ # NotImplementedError), so let's try to read the attribute directly
+ try:
+ # In case the object does weird things with attribute access
+ # such that accessing `obj.__dict__` may raise an exception
+ return obj.__dict__[name]
+ except Exception:
+ pass
+
# this is a catch-all for all the weird things that some modules do
# with attribute access
if defargs:
return defargs[0]
+
raise AttributeError(name)
diff --git a/sphinx/util/jsdump.py b/sphinx/util/jsdump.py
index fd553bd40..43c2962f1 100644
--- a/sphinx/util/jsdump.py
+++ b/sphinx/util/jsdump.py
@@ -19,7 +19,7 @@ from sphinx.util.pycompat import u
_str_re = re.compile(r'"(\\\\|\\"|[^"])*"')
_int_re = re.compile(r'\d+')
_name_re = re.compile(r'[a-zA-Z]\w*')
-_nameonly_re = re.compile(r'[a-zA-Z]\w*$')
+_nameonly_re = re.compile(r'[a-zA-Z_][a-zA-Z0-9_]*$')
# escape \, ", control characters and everything outside ASCII
ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')
diff --git a/sphinx/util/matching.py b/sphinx/util/matching.py
index 91fda6378..fc7750be9 100644
--- a/sphinx/util/matching.py
+++ b/sphinx/util/matching.py
@@ -62,6 +62,27 @@ def compile_matchers(patterns):
return [re.compile(_translate_pattern(pat)).match for pat in patterns]
+class Matcher(object):
+ """A pattern matcher for Multiple shell-style glob patterns.
+
+ Note: this modifies the patterns to work with copy_asset().
+ For example, "**/index.rst" matches with "index.rst"
+ """
+
+ def __init__(self, patterns):
+ expanded = [pat[3:] for pat in patterns if pat.startswith('**/')]
+ self.patterns = compile_matchers(patterns + expanded)
+
+ def __call__(self, string):
+ return self.match(string)
+
+ def match(self, string):
+ return any(pat(string) for pat in self.patterns)
+
+
+DOTFILES = Matcher(['**/.*'])
+
+
_pat_cache = {}
diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py
index 585dc6104..9586306fd 100644
--- a/sphinx/util/osutil.py
+++ b/sphinx/util/osutil.py
@@ -17,6 +17,7 @@ import time
import errno
import locale
import shutil
+import filecmp
from os import path
import contextlib
@@ -141,13 +142,16 @@ def copytimes(source, dest):
def copyfile(source, dest):
- """Copy a file and its modification times, if possible."""
- shutil.copyfile(source, dest)
- try:
- # don't do full copystat because the source may be read-only
- copytimes(source, dest)
- except OSError:
- pass
+ """Copy a file and its modification times, if possible.
+
+ Note: ``copyfile`` skips copying if the file has not been changed"""
+ if not path.exists(dest) or not filecmp.cmp(source, dest):
+ shutil.copyfile(source, dest)
+ try:
+ # don't do full copystat because the source may be read-only
+ copytimes(source, dest)
+ except OSError:
+ pass
no_fn_re = re.compile(r'[^a-zA-Z0-9_-]')
@@ -213,3 +217,10 @@ def cd(target_dir):
yield
finally:
os.chdir(cwd)
+
+
+def rmtree(path):
+ if os.path.isdir(path):
+ shutil.rmtree(path)
+ else:
+ os.remove(path)
diff --git a/sphinx/util/pycompat.py b/sphinx/util/pycompat.py
index c9474af9b..0f7980e82 100644
--- a/sphinx/util/pycompat.py
+++ b/sphinx/util/pycompat.py
@@ -80,7 +80,7 @@ else:
# error handler
sys_encoding = __import__('locale').getpreferredencoding()
# use Python 3 name
- from cgi import escape as htmlescape # noqa: 2.6, 2.7
+ from cgi import escape as htmlescape # noqa: F401
class UnicodeMixin(object):
"""Mixin class to handle defining the proper __str__/__unicode__
diff --git a/sphinx/util/template.py b/sphinx/util/template.py
new file mode 100644
index 000000000..b89a4c960
--- /dev/null
+++ b/sphinx/util/template.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.template
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Templates utility functions for Sphinx.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+from jinja2.sandbox import SandboxedEnvironment
+
+from sphinx import package_dir
+from sphinx.jinja2glue import SphinxFileSystemLoader
+
+
+class BaseRenderer(object):
+ def __init__(self, loader=None):
+ self.env = SandboxedEnvironment(loader=loader)
+ self.env.filters['repr'] = repr
+
+ def render(self, template_name, context):
+ return self.env.get_template(template_name).render(context)
+
+ def render_string(self, source, context):
+ return self.env.from_string(source).render(context)
+
+
+class FileRenderer(BaseRenderer):
+ def __init__(self, search_path):
+ loader = SphinxFileSystemLoader(search_path)
+ super(FileRenderer, self).__init__(loader)
+
+ @classmethod
+ def render_from_file(cls, filename, context):
+ dirname = os.path.dirname(filename)
+ basename = os.path.basename(filename)
+ return cls(dirname).render(basename, context)
+
+
+class SphinxRenderer(FileRenderer):
+ def __init__(self):
+ super(SphinxRenderer, self).__init__(os.path.join(package_dir, 'templates'))
+
+
+class LaTeXRenderer(SphinxRenderer):
+ def __init__(self):
+ super(LaTeXRenderer, self).__init__()
+
+ # use JSP/eRuby like tagging instead because curly bracket; the default
+ # tagging of jinja2 is not good for LaTeX sources.
+ self.env.variable_start_string = '<%='
+ self.env.variable_end_string = '%>'
+ self.env.block_start_string = '<%'
+ self.env.block_end_string = '%>'
diff --git a/sphinx/websupport/search/__init__.py b/sphinx/websupport/search/__init__.py
index 844a3b468..80b5a3535 100644
--- a/sphinx/websupport/search/__init__.py
+++ b/sphinx/websupport/search/__init__.py
@@ -34,19 +34,20 @@ class BaseSearch(object):
"""
pass
- def feed(self, pagename, title, doctree):
+ def feed(self, pagename, filename, title, doctree):
"""Called by the builder to add a doctree to the index. Converts the
`doctree` to text and passes it to :meth:`add_document`. You probably
won't want to override this unless you need access to the `doctree`.
Override :meth:`add_document` instead.
:param pagename: the name of the page to be indexed
+ :param filename: the name of the original source file
:param title: the title of the page to be indexed
:param doctree: is the docutils doctree representation of the page
"""
- self.add_document(pagename, title, doctree.astext())
+ self.add_document(pagename, filename, title, doctree.astext())
- def add_document(self, pagename, title, text):
+ def add_document(self, pagename, filename, title, text):
"""Called by :meth:`feed` to add a document to the search index.
This method should should do everything necessary to add a single
document to the search index.
@@ -59,6 +60,7 @@ class BaseSearch(object):
query.
:param pagename: the name of the page being indexed
+ :param filename: the name of the original source file
:param title: the page's title
:param text: the full text of the page
"""
diff --git a/sphinx/websupport/search/nullsearch.py b/sphinx/websupport/search/nullsearch.py
index 9e990b1cf..4d0db9553 100644
--- a/sphinx/websupport/search/nullsearch.py
+++ b/sphinx/websupport/search/nullsearch.py
@@ -17,7 +17,7 @@ class NullSearch(BaseSearch):
"""A search adapter that does nothing. Used when no search adapter
is specified.
"""
- def feed(self, pagename, title, doctree):
+ def feed(self, pagename, filename, title, doctree):
pass
def query(self, q):
diff --git a/sphinx/websupport/search/whooshsearch.py b/sphinx/websupport/search/whooshsearch.py
index 4b0769f50..f31dc4d52 100644
--- a/sphinx/websupport/search/whooshsearch.py
+++ b/sphinx/websupport/search/whooshsearch.py
@@ -44,7 +44,7 @@ class WhooshSearch(BaseSearch):
def finish_indexing(self):
self.index_writer.commit()
- def add_document(self, pagename, title, text):
+ def add_document(self, pagename, filename, title, text):
self.index_writer.add_document(path=text_type(pagename),
title=title,
text=text)
diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py
index 7b666aa52..a0ce34575 100644
--- a/sphinx/writers/html.py
+++ b/sphinx/writers/html.py
@@ -439,7 +439,7 @@ class HTMLTranslator(BaseTranslator):
pass
def visit_download_reference(self, node):
- if node.hasattr('filename'):
+ if self.builder.download_support and node.hasattr('filename'):
self.body.append(
'<a class="reference download internal" href="%s" download="">' %
posixpath.join(self.builder.dlpath, node['filename']))
@@ -458,15 +458,14 @@ class HTMLTranslator(BaseTranslator):
node['uri'] = posixpath.join(self.builder.imgpath,
self.builder.images[olduri])
- if node['uri'].lower().endswith('svg') or \
- node['uri'].lower().endswith('svgz'):
- atts = {'src': node['uri']}
+ uri = node['uri']
+ if uri.lower().endswith('svg') or uri.lower().endswith('svgz'):
+ atts = {'src': uri}
if 'width' in node:
atts['width'] = node['width']
if 'height' in node:
atts['height'] = node['height']
- if 'alt' in node:
- atts['alt'] = node['alt']
+ atts['alt'] = node.get('alt', uri)
if 'align' in node:
self.body.append('<div align="%s" class="align-%s">' %
(node['align'], node['align']))
diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py
index 2d34ab98f..19eb3e195 100644
--- a/sphinx/writers/latex.py
+++ b/sphinx/writers/latex.py
@@ -28,42 +28,10 @@ from sphinx.locale import admonitionlabels, _
from sphinx.util import split_into
from sphinx.util.i18n import format_date
from sphinx.util.nodes import clean_astext, traverse_parent
+from sphinx.util.template import LaTeXRenderer
from sphinx.util.texescape import tex_escape_map, tex_replace_map
from sphinx.util.smartypants import educate_quotes_latex
-HEADER = r'''%% Generated by Sphinx.
-\def\sphinxdocclass{%(docclass)s}
-\documentclass[%(papersize)s,%(pointsize)s%(classoptions)s]{%(wrapperclass)s}
-\usepackage{iftex}
-%(passoptionstopackages)s
-%(inputenc)s
-%(utf8extra)s
-%(cmappkg)s
-%(fontenc)s
-%(amsmath)s
-%(babel)s
-%(fontpkg)s
-%(fncychap)s
-%(longtable)s
-\usepackage{sphinx}
-\usepackage{multirow}
-\usepackage{eqparbox}
-%(usepackages)s
-%(contentsname)s
-%(numfig_format)s
-%(pageautorefname)s
-%(tocdepth)s
-%(secnumdepth)s
-%(preamble)s
-
-\title{%(title)s}
-\date{%(date)s}
-\release{%(release)s}
-\author{%(author)s}
-\newcommand{\sphinxlogo}{%(logo)s}
-\renewcommand{\releasename}{%(releasename)s}
-%(makeindex)s
-'''
BEGIN_DOC = r'''
\begin{document}
@@ -72,12 +40,8 @@ BEGIN_DOC = r'''
%(tableofcontents)s
'''
-FOOTER = r'''
-\renewcommand{\indexname}{%(indexname)s}
-%(printindex)s
-\end{document}
-'''
+DEFAULT_TEMPLATE = 'latex/content.tex_t'
URI_SCHEMES = ('mailto:', 'http:', 'https:', 'ftp:')
SECNUMDEPTH = 3
@@ -266,27 +230,26 @@ class Table(object):
self.longtable = False
-def width_to_latex_length(length_str):
- """Convert `length_str` with rst length to LaTeX length.
-
- This function is copied from docutils' latex writer
- """
- match = re.match('(\d*\.?\d*)\s*(\S*)', length_str)
- if not match:
- return length_str
- value, unit = match.groups()[:2]
- if unit in ('', 'pt'):
- length_str = '%sbp' % value # convert to 'bp'
- # percentage: relate to current line width
- elif unit == '%':
- length_str = '%.3f\\linewidth' % (float(value)/100.0)
-
- return length_str
-
-
def escape_abbr(text):
"""Adjust spacing after abbreviations."""
- return text.replace('.', '.\\@')
+ return re.sub('\.(?=\s|$)', '.\\@', text)
+
+
+def rstdim_to_latexdim(width_str):
+ """Convert `width_str` with rst length to LaTeX length."""
+ match = re.match('^(\d*\.?\d*)\s*(\S*)$', width_str)
+ if not match:
+ raise ValueError
+ res = width_str
+ amount, unit = match.groups()[:2]
+ float(amount) # validate amount is float
+ if unit in ('', "px"):
+ res = "%s\\sphinxpxdimen" % amount
+ elif unit == 'pt':
+ res = '%sbp' % amount # convert to 'bp'
+ elif unit == "%":
+ res = "%.3f\\linewidth" % (float(amount) / 100.0)
+ return res
class LaTeXTranslator(nodes.NodeVisitor):
@@ -298,15 +261,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
default_elements = {
'papersize': 'letterpaper',
'pointsize': '10pt',
+ 'pxunit': '49336sp',
'classoptions': '',
'extraclassoptions': '',
'passoptionstopackages': '',
- 'inputenc': ('\\ifPDFTeX\n'
- ' \\usepackage[utf8]{inputenc}\n'
- '\\else\\fi'),
+ 'inputenc': '',
'utf8extra': ('\\ifdefined\\DeclareUnicodeCharacter\n'
' \\DeclareUnicodeCharacter{00A0}{\\nobreakspace}\n'
- '\\else\\fi'),
+ '\\fi'),
'cmappkg': '\\usepackage{cmap}',
'fontenc': '\\usepackage[T1]{fontenc}',
'amsmath': '\\usepackage{amsmath,amssymb,amstext}',
@@ -371,41 +333,39 @@ class LaTeXTranslator(nodes.NodeVisitor):
if document.settings.docclass == 'howto':
self.top_sectionlevel = 2
else:
- if builder.config.latex_use_parts:
- self.top_sectionlevel = 0
- else:
- self.top_sectionlevel = 1
+ self.top_sectionlevel = 1
# sort out some elements
- papersize = builder.config.latex_paper_size + 'paper'
- if papersize == 'paper': # e.g. command line "-D latex_paper_size="
- papersize = 'letterpaper'
-
self.elements = self.default_elements.copy()
self.elements.update({
'wrapperclass': self.format_docclass(document.settings.docclass),
- 'papersize': papersize,
- 'pointsize': builder.config.latex_font_size,
# if empty, the title is set to the first section title
'title': document.settings.title,
'release': builder.config.release,
'author': document.settings.author,
'releasename': _('Release'),
- 'preamble': builder.config.latex_preamble,
'indexname': _('Index'),
})
+ # set-up boolean for sphinx.sty
+ if builder.config.latex_keep_old_macro_names:
+ self.elements['keepoldnames'] = '\\sphinxKeepOldNamestrue'
+ else:
+ self.elements['keepoldnames'] = '\\sphinxKeepOldNamesfalse'
if document.settings.docclass == 'howto':
docclass = builder.config.latex_docclass.get('howto', 'article')
else:
docclass = builder.config.latex_docclass.get('manual', 'report')
self.elements['docclass'] = docclass
+ if builder.config.latex_engine == 'pdflatex':
+ self.elements['inputenc'] = '\\usepackage[utf8]{inputenc}'
if builder.config.today:
self.elements['date'] = builder.config.today
else:
self.elements['date'] = format_date(builder.config.today_fmt or _('%b %d, %Y'),
language=builder.config.language)
if builder.config.latex_logo:
- self.elements['logo'] = '\\includegraphics{%s}\\par' % \
+ # no need for \\noindent here, used in flushright
+ self.elements['logo'] = '\\sphinxincludegraphics{%s}\\par' % \
path.basename(builder.config.latex_logo)
# setup babel
self.babel = ExtBabel(builder.config.language)
@@ -458,6 +418,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.elements['contentsname'] = \
self.babel_renewcommand('\\contentsname', document.settings.contentsname)
# allow the user to override them all
+ self.check_latex_elements()
self.elements.update(builder.config.latex_elements)
if self.elements['extraclassoptions']:
self.elements['classoptions'] += ',' + \
@@ -505,6 +466,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
def pop_hyperlink_ids(self, figtype):
return self.next_hyperlink_ids.pop(figtype, set())
+ def check_latex_elements(self):
+ for key in self.builder.config.latex_elements:
+ if key not in self.elements:
+ msg = _("Unknown configure key: latex_elements[%r] is ignored.")
+ self.builder.warn(msg % key)
+
def restrict_footnote(self, node):
if self.footnote_restricted is False:
self.footnote_restricted = node
@@ -526,12 +493,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
return docclass
def astext(self):
- return (HEADER % self.elements +
- self.highlighter.get_stylesheet() +
- u''.join(self.body) +
- '\n' + self.elements['footer'] + '\n' +
- self.generate_indices() +
- FOOTER % self.elements)
+ self.elements.update({
+ 'body': u''.join(self.body),
+ 'indices': self.generate_indices()
+ })
+ return LaTeXRenderer().render(DEFAULT_TEMPLATE, self.elements)
def hypertarget(self, id, withdoc=True, anchor=True):
if withdoc:
@@ -605,9 +571,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
if len(codeblock) == 1:
pass # FIXME
else:
- ret.append('\\SetupFloatingEnvironment{literal-block}{name=%s}\n' %
- escape_abbr(text_type(codeblock[0]).translate(tex_escape_map)))
- if table[1]:
+ definition = escape_abbr(text_type(codeblock[0]).translate(tex_escape_map))
+ ret.append(self.babel_renewcommand('\\literalblockname', definition))
+ if codeblock[1]:
pass # FIXME
return ''.join(ret)
@@ -625,11 +591,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
for entry in entries:
if not entry[3]:
continue
- ret.append('\\item {\\texttt{%s}}' % self.encode(entry[0]))
+ ret.append('\\item {\\sphinxstyleindexentry{%s}}' % self.encode(entry[0]))
if entry[4]:
# add "extra" info
- ret.append(' \\emph{(%s)}' % self.encode(entry[4]))
- ret.append(', \\pageref{%s:%s}\n' %
+ ret.append('\\sphinxstyleindexextra{%s}' % self.encode(entry[4]))
+ ret.append('\\sphinxstyleindexpageref{%s:%s}\n' %
(entry[2], self.idescape(entry[3])))
ret.append('\\end{theindex}\n')
@@ -743,11 +709,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_topic(self, node):
self.in_minipage = 1
- self.body.append('\n\\begin{SphinxShadowBox}\n')
+ self.body.append('\n\\begin{sphinxShadowBox}\n')
def depart_topic(self, node):
self.in_minipage = 0
- self.body.append('\\end{SphinxShadowBox}\n')
+ self.body.append('\\end{sphinxShadowBox}\n')
visit_sidebar = visit_topic
depart_sidebar = depart_topic
@@ -817,9 +783,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.context[-1] += self.hypertarget(id, anchor=False)
self.next_section_ids.clear()
- elif isinstance(parent, (nodes.topic, nodes.sidebar)):
- self.body.append(r'\textbf{')
- self.context.append('}\n\n\medskip\n\n')
+ elif isinstance(parent, nodes.topic):
+ self.body.append(r'\sphinxstyletopictitle{')
+ self.context.append('}\n')
+ elif isinstance(parent, nodes.sidebar):
+ self.body.append(r'\sphinxstylesidebartitle{')
+ self.context.append('}\n')
elif isinstance(parent, nodes.Admonition):
self.body.append('{')
self.context.append('}\n')
@@ -831,7 +800,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
'encountered title node not in section, topic, table, '
'admonition or sidebar',
(self.curfilestack[-1], node.line or ''))
- self.body.append('\\textbf{')
+ self.body.append('\\sphinxstyleothertitle{')
self.context.append('}\n')
self.in_title = 1
@@ -845,8 +814,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_subtitle(self, node):
if isinstance(node.parent, nodes.sidebar):
- self.body.append('~\\\\\n\\textbf{')
- self.context.append('}\n\\smallskip\n')
+ self.body.append('\\sphinxstylesidebarsubtitle{')
+ self.context.append('}\n')
else:
self.context.append('')
@@ -878,7 +847,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('}')
def visit_desc_addname(self, node):
- self.body.append(r'\code{')
+ self.body.append(r'\sphinxcode{')
self.literal_whitespace += 1
def depart_desc_addname(self, node):
@@ -898,7 +867,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append(r'}')
def visit_desc_name(self, node):
- self.body.append(r'\bfcode{')
+ self.body.append(r'\sphinxbfcode{')
self.no_contractions += 1
self.literal_whitespace += 1
@@ -929,13 +898,13 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('}')
def visit_desc_optional(self, node):
- self.body.append(r'\optional{')
+ self.body.append(r'\sphinxoptional{')
def depart_desc_optional(self, node):
self.body.append('}')
def visit_desc_annotation(self, node):
- self.body.append(r'\strong{')
+ self.body.append(r'\sphinxstrong{')
def depart_desc_annotation(self, node):
self.body.append('}')
@@ -949,7 +918,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
pass
def visit_seealso(self, node):
- self.body.append(u'\n\n\\strong{%s:}\n\n' % admonitionlabels['seealso'])
+ self.body.append(u'\n\n\\sphinxstrong{%s:}\n\n' % admonitionlabels['seealso'])
def depart_seealso(self, node):
self.body.append("\n\n")
@@ -972,9 +941,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_collected_footnote(self, node):
self.in_footnote += 1
if 'footnotetext' in node:
- self.body.append('\\footnotetext[%s]{\sphinxAtStartFootnote%%' % node['number'])
+ self.body.append('\\footnotetext[%s]{\sphinxAtStartFootnote\n' % node['number'])
else:
- self.body.append('\\footnote[%s]{\sphinxAtStartFootnote%%' % node['number'])
+ self.body.append('\\footnote[%s]{\sphinxAtStartFootnote\n' % node['number'])
def depart_collected_footnote(self, node):
self.body.append('}')
@@ -1022,23 +991,23 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('\n\\begin{longtable}')
endmacro = '\\end{longtable}\n\n'
elif self.table.has_verbatim:
- self.body.append('\n\\begin{tabular}')
+ self.body.append('\n\\noindent\\begin{tabular}')
endmacro = '\\end{tabular}\n\n'
elif self.table.has_problematic and not self.table.colspec:
# if the user has given us tabularcolumns, accept them and use
# tabulary nevertheless
- self.body.append('\n\\begin{tabular}')
+ self.body.append('\n\\noindent\\begin{tabular}')
endmacro = '\\end{tabular}\n\n'
else:
- self.body.append('\n\\begin{tabulary}{\\linewidth}')
+ self.body.append('\n\\noindent\\begin{tabulary}{\\linewidth}')
endmacro = '\\end{tabulary}\n\n'
if self.table.colspec:
self.body.append(self.table.colspec)
else:
if self.table.has_problematic:
- colwidth = 0.95 / self.table.colcount
- colspec = ('p{%.3f\\linewidth}|' % colwidth) * \
- self.table.colcount
+ colspec = ('*{%d}{p{\\dimexpr(\\linewidth-\\arrayrulewidth)/%d'
+ '-2\\tabcolsep-\\arrayrulewidth\\relax}|}' %
+ (self.table.colcount, self.table.colcount))
self.body.append('{|' + colspec + '}\n')
elif self.table.longtable:
self.body.append('{|' + ('l|' * self.table.colcount) + '}\n')
@@ -1143,28 +1112,28 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.remember_multirow[self.table.col] -= 1
if self.remember_multirowcol.get(self.table.col, 0):
extracols = self.remember_multirowcol[self.table.col]
- self.body.append(' \\multicolumn{')
+ self.body.append('\\multicolumn{')
self.body.append(str(extracols + 1))
- self.body.append('}{|l|}{}')
+ self.body.append('}{|l|}{}\\relax ')
self.table.col += extracols
- self.body.append(' & ')
+ self.body.append('&')
else:
- self.body.append(' & ')
+ self.body.append('&')
self.table.col += 1
context = ''
if 'morecols' in node:
- self.body.append(' \\multicolumn{')
+ self.body.append('\\multicolumn{')
self.body.append(str(node.get('morecols') + 1))
if self.table.col == 1:
- self.body.append('}{|l|}{')
+ self.body.append('}{|l|}{\\relax ')
else:
- self.body.append('}{l|}{')
- context += '}'
+ self.body.append('}{l|}{\\relax ')
+ context += '\\unskip}\\relax '
if 'morerows' in node:
- self.body.append(' \\multirow{')
+ self.body.append('\\multirow{')
self.body.append(str(node.get('morerows') + 1))
- self.body.append('}{*}{')
- context += '}'
+ self.body.append('}{*}{\\relax ')
+ context += '\\unskip}\\relax '
self.remember_multirow[self.table.col] = node.get('morerows')
if 'morecols' in node:
if 'morerows' in node:
@@ -1181,17 +1150,17 @@ class LaTeXTranslator(nodes.NodeVisitor):
if len(node) == 1 and isinstance(node[0], nodes.paragraph) and node.astext() == '':
pass
else:
- self.body.append('\\textsf{\\relax ')
- context += '}'
+ self.body.append('\\sphinxstylethead{\\relax ')
+ context += '\\unskip}\\relax '
while self.remember_multirow.get(self.table.col + 1, 0):
self.table.col += 1
self.remember_multirow[self.table.col] -= 1
- context += ' & '
+ context += '&'
if self.remember_multirowcol.get(self.table.col, 0):
extracols = self.remember_multirowcol[self.table.col]
- context += ' \\multicolumn{'
+ context += '\\multicolumn{'
context += str(extracols + 1)
- context += '}{l|}{}'
+ context += '}{l|}{}\\relax '
self.table.col += extracols
if len(node.traverse(nodes.paragraph)) >= 2:
self.table.has_problematic = True
@@ -1314,12 +1283,15 @@ class LaTeXTranslator(nodes.NodeVisitor):
depart_field_body = depart_definition
def visit_paragraph(self, node):
- # insert blank line, if the paragraph follows a non-paragraph node in a compound
index = node.parent.index(node)
if (index > 0 and isinstance(node.parent, nodes.compound) and
not isinstance(node.parent[index - 1], nodes.paragraph) and
not isinstance(node.parent[index - 1], nodes.compound)):
+ # insert blank line, if the paragraph follows a non-paragraph node in a compound
self.body.append('\\noindent\n')
+ elif index == 0 and isinstance(node.parent, nodes.footnote):
+ # don't insert blank line, if the paragraph is first child of a footnote
+ pass
else:
self.body.append('\n')
@@ -1354,18 +1326,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
pass
def latex_image_length(self, width_str):
- match = re.match('(\d*\.?\d*)\s*(\S*)', width_str)
- if not match:
- # fallback
- return width_str
- res = width_str
- amount, unit = match.groups()[:2]
- if not unit or unit == "px":
- # pixels: let LaTeX alone
- return None
- elif unit == "%":
- res = "%.3f\\linewidth" % (float(amount) / 100.0)
- return res
+ try:
+ return rstdim_to_latexdim(width_str)
+ except ValueError:
+ self.builder.warn('dimension unit %s is invalid. Ignored.' % width_str)
def is_inline(self, node):
"""Check whether a node represents an inline element."""
@@ -1409,7 +1373,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
except KeyError:
pass
if not is_inline:
- pre.append('\n')
+ pre.append('\n\\noindent')
post.append('\n')
pre.reverse()
if node['uri'] in self.builder.images:
@@ -1427,7 +1391,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
if include_graphics_options:
options = '[%s]' % ','.join(include_graphics_options)
base, ext = path.splitext(uri)
- self.body.append('\\includegraphics%s{{%s}%s}' % (options, base, ext))
+ if self.in_title and base:
+ # Lowercase tokens forcely because some fncychap themes capitalize
+ # the options of \sphinxincludegraphics unexpectly (ex. WIDTH=...).
+ self.body.append('\\lowercase{\\sphinxincludegraphics%s}{{%s}%s}' %
+ (options, base, ext))
+ else:
+ self.body.append('\\sphinxincludegraphics%s{{%s}%s}' %
+ (options, base, ext))
self.body.extend(post)
def depart_image(self, node):
@@ -1444,13 +1415,26 @@ class LaTeXTranslator(nodes.NodeVisitor):
isinstance(node.children[0], nodes.image) and
node.children[0]['ids']):
ids += self.hypertarget(node.children[0]['ids'][0], anchor=False)
- if node.get('align', '') in ('left', 'right'):
+ if self.table:
+ # TODO: support align option
if 'width' in node:
- length = width_to_latex_length(node['width'])
+ length = self.latex_image_length(node['width'])
+ if length:
+ self.body.append('\\begin{sphinxfigure-in-table}[%s]\n'
+ '\\centering\n' % length)
else:
- length = '0pt'
+ self.body.append('\\begin{sphinxfigure-in-table}\n\\centering\n')
+ if any(isinstance(child, nodes.caption) for child in node):
+ self.body.append('\\capstart')
+ self.context.append(ids + '\\end{sphinxfigure-in-table}\\relax\n')
+ elif node.get('align', '') in ('left', 'right'):
+ length = None
+ if 'width' in node:
+ length = self.latex_image_length(node['width'])
+ elif 'width' in node[0]:
+ length = self.latex_image_length(node[0]['width'])
self.body.append('\\begin{wrapfigure}{%s}{%s}\n\\centering' %
- (node['align'] == 'right' and 'r' or 'l', length))
+ (node['align'] == 'right' and 'r' or 'l', length or '0pt'))
self.context.append(ids + '\\end{wrapfigure}\n')
elif self.in_minipage:
if ('align' not in node.attributes or
@@ -1483,9 +1467,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_caption(self, node):
self.in_caption += 1
if self.in_container_literal_block:
- self.body.append('\\SphinxSetupCaptionForVerbatim{literal-block}{')
+ self.body.append('\\sphinxSetupCaptionForVerbatim{')
elif self.in_minipage and isinstance(node.parent, nodes.figure):
self.body.append('\\captionof{figure}{')
+ elif self.table and node.parent.tagname == 'figure':
+ self.body.append('\\sphinxfigcaption{')
else:
self.body.append('\\caption{')
@@ -1500,19 +1486,19 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('}')
def visit_admonition(self, node):
- self.body.append('\n\\begin{notice}{note}')
+ self.body.append('\n\\begin{sphinxadmonition}{note}')
def depart_admonition(self, node):
- self.body.append('\\end{notice}\n')
+ self.body.append('\\end{sphinxadmonition}\n')
def _make_visit_admonition(name):
def visit_admonition(self, node):
- self.body.append(u'\n\\begin{notice}{%s}{%s:}' %
+ self.body.append(u'\n\\begin{sphinxadmonition}{%s}{%s:}' %
(name, admonitionlabels[name]))
return visit_admonition
def _depart_named_admonition(self, node):
- self.body.append('\\end{notice}\n')
+ self.body.append('\\end{sphinxadmonition}\n')
visit_attention = _make_visit_admonition('attention')
depart_attention = _depart_named_admonition
@@ -1683,9 +1669,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
# don't add a pageref for glossary terms
self.context.append('}}}')
# mark up as termreference
- self.body.append(r'\termref{')
+ self.body.append(r'\sphinxtermref{')
else:
- self.body.append(r'\crossref{')
+ self.body.append(r'\sphinxcrossref{')
if self.builder.config.latex_show_pagerefs and not \
self.in_production_list:
self.context.append('}}} (%s)' % self.hyperpageref(id))
@@ -1726,36 +1712,36 @@ class LaTeXTranslator(nodes.NodeVisitor):
pass
def visit_emphasis(self, node):
- self.body.append(r'\emph{')
+ self.body.append(r'\sphinxstyleemphasis{')
def depart_emphasis(self, node):
self.body.append('}')
def visit_literal_emphasis(self, node):
- self.body.append(r'\emph{\texttt{')
+ self.body.append(r'\sphinxstyleliteralemphasis{')
self.no_contractions += 1
def depart_literal_emphasis(self, node):
- self.body.append('}}')
+ self.body.append('}')
self.no_contractions -= 1
def visit_strong(self, node):
- self.body.append(r'\textbf{')
+ self.body.append(r'\sphinxstylestrong{')
def depart_strong(self, node):
self.body.append('}')
def visit_literal_strong(self, node):
- self.body.append(r'\textbf{\texttt{')
+ self.body.append(r'\sphinxstyleliteralstrong{')
self.no_contractions += 1
def depart_literal_strong(self, node):
- self.body.append('}}')
+ self.body.append('}')
self.no_contractions -= 1
def visit_abbreviation(self, node):
abbr = node.astext()
- self.body.append(r'\textsc{')
+ self.body.append(r'\sphinxstyleabbreviation{')
# spell out the explanation once
if node.hasattr('explanation') and abbr not in self.handled_abbrs:
self.context.append('} (%s)' % self.encode(node['explanation']))
@@ -1773,7 +1759,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
return self.depart_literal_emphasis(node)
def visit_title_reference(self, node):
- self.body.append(r'\titleref{')
+ self.body.append(r'\sphinxtitleref{')
def depart_title_reference(self, node):
self.body.append('}')
@@ -1799,9 +1785,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_literal(self, node):
self.no_contractions += 1
if self.in_title:
- self.body.append(r'\texttt{')
+ self.body.append(r'\sphinxstyleliteralintitle{')
else:
- self.body.append(r'\code{')
+ self.body.append(r'\sphinxcode{')
def depart_literal(self, node):
self.no_contractions -= 1
@@ -1849,7 +1835,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
ids += self.hypertarget(node['ids'][0], anchor=False)
# LaTeX code will insert \phantomsection prior to \label
if ids:
- self.body.append('\n\\def\\SphinxLiteralBlockLabel{' + ids + '}')
+ self.body.append('\n\\def\\sphinxLiteralBlockLabel{' + ids + '}')
code = node.astext()
lang = self.hlsettingstack[-1][0]
linenos = code.count('\n') >= self.hlsettingstack[-1][1] - 1
@@ -1873,18 +1859,22 @@ class LaTeXTranslator(nodes.NodeVisitor):
**highlight_args)
# workaround for Unicode issue
hlcode = hlcode.replace(u'€', u'@texteuro[]')
- # must use original Verbatim environment and "tabular" environment
+ # if in table raise verbatim flag to avoid "tabulary" environment
+ # and opt for sphinxVerbatimintable to handle caption & long lines
if self.table:
- hlcode = hlcode.replace('\\begin{Verbatim}',
- '\\begin{OriginalVerbatim}')
self.table.has_problematic = True
self.table.has_verbatim = True
+ hlcode = hlcode.replace('\\begin{Verbatim}',
+ '\\begin{sphinxVerbatimintable}')
+ else:
+ hlcode = hlcode.replace('\\begin{Verbatim}',
+ '\\begin{sphinxVerbatim}')
# get consistent trailer
hlcode = hlcode.rstrip()[:-14] # strip \end{Verbatim}
- self.body.append('\n' + hlcode + '\\end{%sVerbatim}\n' %
- (self.table and 'Original' or ''))
+ self.body.append('\n' + hlcode + '\\end{sphinxVerbatim%s}\n' %
+ (self.table and 'intable' or ''))
if ids:
- self.body.append('\\let\\SphinxLiteralBlockLabel\empty\n')
+ self.body.append('\\let\\sphinxLiteralBlockLabel\empty\n')
raise nodes.SkipNode
def depart_literal_block(self, node):
@@ -2010,10 +2000,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_inline(self, node):
classes = node.get('classes', [])
if classes in [['menuselection'], ['guilabel']]:
- self.body.append(r'\menuselection{')
+ self.body.append(r'\sphinxmenuselection{')
self.context.append('}')
elif classes in [['accelerator']]:
- self.body.append(r'\accelerator{')
+ self.body.append(r'\sphinxaccelerator{')
self.context.append('}')
elif classes and not self.in_title:
self.body.append(r'\DUrole{%s}{' % ','.join(classes))
@@ -2047,13 +2037,13 @@ class LaTeXTranslator(nodes.NodeVisitor):
ids += self.hypertarget(node['ids'][0], anchor=False)
# define label for use in caption.
if ids:
- self.body.append('\n\\def\\SphinxLiteralBlockLabel{' + ids + '}\n')
+ self.body.append('\n\\def\\sphinxLiteralBlockLabel{' + ids + '}\n')
def depart_container(self, node):
if node.get('literal_block'):
self.in_container_literal_block -= 1
- self.body.append('\\let\\SphinxVerbatimTitle\\empty\n')
- self.body.append('\\let\\SphinxLiteralBlockLabel\\empty\n')
+ self.body.append('\\let\\sphinxVerbatimTitle\\empty\n')
+ self.body.append('\\let\\sphinxLiteralBlockLabel\\empty\n')
def visit_decoration(self, node):
pass
diff --git a/test-reqs.txt b/test-reqs.txt
index 582afe69f..e0eb41ebd 100644
--- a/test-reqs.txt
+++ b/test-reqs.txt
@@ -1,5 +1,6 @@
flake8
nose
+nose-timer
mock
six>=1.4
Jinja2>=2.3
@@ -13,3 +14,4 @@ alabaster
sphinx_rtd_theme
imagesize
requests
+html5lib
diff --git a/tests/coverage.py b/tests/coverage.py
index f9341d8ba..cd36e218a 100755
--- a/tests/coverage.py
+++ b/tests/coverage.py
@@ -472,10 +472,9 @@ class coverage:
def save(self):
if self.usecache and self.cache:
self.canonicalize_filenames()
- cache = open(self.cache, 'wb')
import marshal
- marshal.dump(self.cexecuted, cache)
- cache.close()
+ with open(self.cache, 'wb') as cache:
+ marshal.dump(self.cexecuted, cache)
# restore(). Restore coverage data from the coverage cache (if it exists).
@@ -488,10 +487,9 @@ class coverage:
def restore_file(self, file_name):
try:
- cache = open(file_name, 'rb')
import marshal
- cexecuted = marshal.load(cache)
- cache.close()
+ with open(file_name, 'rb') as cache:
+ cexecuted = marshal.load(cache)
if isinstance(cexecuted, dict):
return cexecuted
else:
@@ -614,8 +612,8 @@ class coverage:
)
filename = filename[:-1]
if not source:
- sourcef = open(filename, 'rU')
- source = sourcef.read()
+ with open(filename, 'rU') as sourcef:
+ source = sourcef.read()
try:
lines, excluded_lines, line_map = self.find_executable_statements(
source, exclude=self.exclude_re
@@ -625,8 +623,6 @@ class coverage:
"Couldn't parse '%s' as Python source: '%s' at line %d" %
(filename, synerr.msg, synerr.lineno)
)
- if sourcef:
- sourcef.close()
result = filename, lines, excluded_lines, line_map
self.analysis_cache[morf] = result
return result
diff --git a/tests/path.py b/tests/path.py
index 901c9ce96..959b54875 100755
--- a/tests/path.py
+++ b/tests/path.py
@@ -206,10 +206,13 @@ class path(text_type):
class _repr_text(text_type):
def __repr__(self):
return self._repr
+
+
class _repr_bin(binary_type):
def __repr__(self):
return self._repr
+
def repr_as(string, repr_):
wrapper = _repr_text if isinstance(string, text_type) else _repr_bin
proxy = wrapper(string)
diff --git a/tests/root/footnote.txt b/tests/root/footnote.txt
index 36ad3fadc..a040f10f3 100644
--- a/tests/root/footnote.txt
+++ b/tests/root/footnote.txt
@@ -53,9 +53,3 @@ footenotes
.. [#] footnotes in table caption
.. [#] footnotes in table
-
-
-missing target
---------------------
-[missing]_ citation
-
diff --git a/tests/root/images.txt b/tests/root/images.txt
index e78f8be3c..3dd8e6957 100644
--- a/tests/root/images.txt
+++ b/tests/root/images.txt
@@ -15,9 +15,6 @@ Sphinx image handling
.. an image with unspecified extension
.. image:: img.*
-.. a non-existing image with .*
-.. image:: foo.*
-
.. a non-local image URI
.. image:: http://www.python.org/logo.png
diff --git a/tests/root/img.foo.png b/tests/root/img.foo.png
index 4c8f89929..a97e86d66 100644
--- a/tests/root/img.foo.png
+++ b/tests/root/img.foo.png
Binary files differ
diff --git a/tests/root/img.png b/tests/root/img.png
index 4c8f89929..a97e86d66 100644
--- a/tests/root/img.png
+++ b/tests/root/img.png
Binary files differ
diff --git a/tests/root/includes.txt b/tests/root/includes.txt
index 41b72b0ab..e921a966c 100644
--- a/tests/root/includes.txt
+++ b/tests/root/includes.txt
@@ -15,10 +15,6 @@ Test file and literal inclusion
.. literalinclude:: literal.inc
:language: python
-.. should give a warning
-.. literalinclude:: wrongenc.inc
- :language: none
-
.. should succeed
.. literalinclude:: wrongenc.inc
:encoding: latin-1
diff --git a/tests/root/markup.txt b/tests/root/markup.txt
index cc1fa2a63..714dabe8d 100644
--- a/tests/root/markup.txt
+++ b/tests/root/markup.txt
@@ -161,7 +161,6 @@ Adding \n to test unescaping.
* :doc:`subdir/includes`
* ``:download:`` is tested in includes.txt
* :option:`Python -c option <python -c>`
-* This used to crash: :option:`&option`
Test :abbr:`abbr (abbreviation)` and another :abbr:`abbr (abbreviation)`.
@@ -220,6 +219,13 @@ Tables with multirow and multicol:
| |
+----+
+.. list-table::
+ :header-rows: 0
+
+ * - .. figure:: img.png
+
+ figure in table
+
Figures
-------
@@ -246,6 +252,12 @@ Figures
figure with align & figwidth option
+.. figure:: rimg.png
+ :align: right
+ :width: 3cm
+
+ figure with align & width option
+
Version markup
--------------
@@ -282,13 +294,6 @@ Code blocks
false
end
-.. code-block:: c
-
- import sys
-
- sys.stdout.write('hello world!\n')
-
-
Misc stuff
----------
@@ -368,13 +373,6 @@ Index markup
see: from; to
seealso: fromalso; toalso
-Invalid index markup...
-
-.. index::
- single:
- pair:
- keyword:
-
.. index::
!Main, !Other
!single: entry; pair
diff --git a/tests/root/objects.txt b/tests/root/objects.txt
index cd711070f..3756677e9 100644
--- a/tests/root/objects.txt
+++ b/tests/root/objects.txt
@@ -93,7 +93,7 @@ Referring to :func:`nothing <>`.
* expression
:returns: a new :class:`Time` instance
:rtype: Time
- :raises ValueError: if the values are out of range
+ :raises Error: if the values are out of range
:ivar int hour: like *hour*
:ivar minute: like *minute*
:vartype minute: int
diff --git a/tests/root/rimg.png b/tests/root/rimg.png
index 1081dc143..fda6cd29e 100644
--- a/tests/root/rimg.png
+++ b/tests/root/rimg.png
Binary files differ
diff --git a/tests/root/subdir/img.png b/tests/root/subdir/img.png
index 4c8f89929..a97e86d66 100644
--- a/tests/root/subdir/img.png
+++ b/tests/root/subdir/img.png
Binary files differ
diff --git a/tests/root/subdir/simg.png b/tests/root/subdir/simg.png
index 4c8f89929..a97e86d66 100644
--- a/tests/root/subdir/simg.png
+++ b/tests/root/subdir/simg.png
Binary files differ
diff --git a/tests/root/testtheme/static/staticimg.png b/tests/root/testtheme/static/staticimg.png
index 1081dc143..fda6cd29e 100644
--- a/tests/root/testtheme/static/staticimg.png
+++ b/tests/root/testtheme/static/staticimg.png
Binary files differ
diff --git a/tests/roots/test-add_enumerable_node/rimg.png b/tests/roots/test-add_enumerable_node/rimg.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-add_enumerable_node/rimg.png
+++ b/tests/roots/test-add_enumerable_node/rimg.png
Binary files differ
diff --git a/tests/roots/test-basic/conf.py b/tests/roots/test-basic/conf.py
new file mode 100644
index 000000000..31e7a6ed4
--- /dev/null
+++ b/tests/roots/test-basic/conf.py
@@ -0,0 +1,7 @@
+# -*- coding: utf-8 -*-
+
+master_doc = 'index'
+
+latex_documents = [
+ (master_doc, 'test.tex', 'The basic Sphinx documentation for testing', 'Sphinx', 'report')
+]
diff --git a/tests/roots/test-basic/index.rst b/tests/roots/test-basic/index.rst
new file mode 100644
index 000000000..8c4ca7d80
--- /dev/null
+++ b/tests/roots/test-basic/index.rst
@@ -0,0 +1,29 @@
+The basic Sphinx documentation for testing
+==========================================
+
+Sphinx is a tool that makes it easy to create intelligent and beautiful
+documentation for Python projects (or other documents consisting of multiple
+reStructuredText sources), written by Georg Brandl. It was originally created
+for the new Python documentation, and has excellent facilities for Python
+project documentation, but C/C++ is supported as well, and more languages are
+planned.
+
+Sphinx uses reStructuredText as its markup language, and many of its strengths
+come from the power and straightforwardness of reStructuredText and its parsing
+and translating suite, the Docutils.
+
+Among its features are the following:
+
+* Output formats: HTML (including derivative formats such as HTML Help, Epub
+ and Qt Help), plain text, manual pages and LaTeX or direct PDF output
+ using rst2pdf
+* Extensive cross-references: semantic markup and automatic links
+ for functions, classes, glossary terms and similar pieces of information
+* Hierarchical structure: easy definition of a document tree, with automatic
+ links to siblings, parents and children
+* Automatic indices: general index as well as a module index
+* Code handling: automatic highlighting using the Pygments highlighter
+* Flexible HTML output using the Jinja 2 templating engine
+* Various extensions are available, e.g. for automatic testing of snippets
+ and inclusion of appropriately formatted docstrings
+* Setuptools integration
diff --git a/tests/roots/test-config/conf.py b/tests/roots/test-config/conf.py
index b6075e5cb..1e583d1e0 100644
--- a/tests/roots/test-config/conf.py
+++ b/tests/roots/test-config/conf.py
@@ -1,4 +1,4 @@
-from sphinx.config import string_classes
+from sphinx.config import string_classes, ENUM
value1 = 123 # wrong type
value2 = 123 # lambda with wrong type
@@ -45,3 +45,4 @@ def setup(app):
app.add_config_value('value14', None, False, string_classes)
app.add_config_value('value15', u'unicode', False)
app.add_config_value('value16', u'unicode', False)
+ app.add_config_value('value17', 'default', False, ENUM('default', 'one', 'two'))
diff --git a/tests/roots/test-ext-math-simple/conf.py b/tests/roots/test-ext-math-simple/conf.py
new file mode 100644
index 000000000..3fe886c17
--- /dev/null
+++ b/tests/roots/test-ext-math-simple/conf.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+
+master_doc = 'index'
+
+latex_documents = [
+ (master_doc, 'test.tex', 'Math Extension Testing', 'Sphinx', 'report')]
diff --git a/tests/roots/test-ext-math-simple/index.rst b/tests/roots/test-ext-math-simple/index.rst
new file mode 100644
index 000000000..a455d8980
--- /dev/null
+++ b/tests/roots/test-ext-math-simple/index.rst
@@ -0,0 +1,4 @@
+Test Math
+=========
+
+.. math:: a^2+b^2=c^2
diff --git a/tests/roots/test-ext-math/math.rst b/tests/roots/test-ext-math/math.rst
new file mode 100644
index 000000000..5a209bed4
--- /dev/null
+++ b/tests/roots/test-ext-math/math.rst
@@ -0,0 +1,31 @@
+Test math extensions :math:`E = m c^2`
+======================================
+
+This is inline math: :math:`a^2 + b^2 = c^2`.
+
+.. math:: a^2 + b^2 = c^2
+
+.. math::
+
+ a + 1 < b
+
+.. math::
+ :label: foo
+
+ e^{i\pi} = 1
+
+.. math::
+ :label:
+
+ e^{ix} = \cos x + i\sin x
+
+.. math::
+
+ n \in \mathbb N
+
+.. math::
+ :nowrap:
+
+ a + 1 < b
+
+Referencing equation :eq:`foo`.
diff --git a/tests/roots/test-ext-todo/bar.rst b/tests/roots/test-ext-todo/bar.rst
new file mode 100644
index 000000000..6804a68c1
--- /dev/null
+++ b/tests/roots/test-ext-todo/bar.rst
@@ -0,0 +1,4 @@
+bar
+===
+
+.. todo:: todo in bar
diff --git a/tests/roots/test-ext-todo/conf.py b/tests/roots/test-ext-todo/conf.py
new file mode 100644
index 000000000..c67a86c5a
--- /dev/null
+++ b/tests/roots/test-ext-todo/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+
+extensions = ['sphinx.ext.todo']
+master_doc = 'index'
diff --git a/tests/roots/test-ext-todo/foo.rst b/tests/roots/test-ext-todo/foo.rst
new file mode 100644
index 000000000..269199977
--- /dev/null
+++ b/tests/roots/test-ext-todo/foo.rst
@@ -0,0 +1,4 @@
+foo
+===
+
+.. todo:: todo in foo
diff --git a/tests/roots/test-ext-todo/index.rst b/tests/roots/test-ext-todo/index.rst
new file mode 100644
index 000000000..6b95f73fd
--- /dev/null
+++ b/tests/roots/test-ext-todo/index.rst
@@ -0,0 +1,9 @@
+test for sphinx.ext.todo
+========================
+
+.. toctree::
+
+ foo
+ bar
+
+.. todolist::
diff --git a/tests/roots/test-footnotes/rimg.png b/tests/roots/test-footnotes/rimg.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-footnotes/rimg.png
+++ b/tests/roots/test-footnotes/rimg.png
Binary files differ
diff --git a/tests/roots/test-html_extra_path/conf.py b/tests/roots/test-html_assets/conf.py
index 53ee62197..a17e417a3 100644
--- a/tests/roots/test-html_extra_path/conf.py
+++ b/tests/roots/test-html_assets/conf.py
@@ -1,6 +1,9 @@
# -*- coding: utf-8 -*-
master_doc = 'index'
+project = 'Sphinx'
+version = '1.4.4'
+html_static_path = ['static', 'subdir']
html_extra_path = ['extra', 'subdir']
exclude_patterns = ['**/_build', '**/.htpasswd']
diff --git a/tests/roots/test-html_extra_path/extra/.htpasswd b/tests/roots/test-html_assets/extra/.htaccess
index e69de29bb..e69de29bb 100644
--- a/tests/roots/test-html_extra_path/extra/.htpasswd
+++ b/tests/roots/test-html_assets/extra/.htaccess
diff --git a/tests/roots/test-html_extra_path/extra/API.html_t b/tests/roots/test-html_assets/extra/.htpasswd
index e69de29bb..e69de29bb 100644
--- a/tests/roots/test-html_extra_path/extra/API.html_t
+++ b/tests/roots/test-html_assets/extra/.htpasswd
diff --git a/tests/roots/test-html_assets/extra/API.html_t b/tests/roots/test-html_assets/extra/API.html_t
new file mode 100644
index 000000000..34ecd9df1
--- /dev/null
+++ b/tests/roots/test-html_assets/extra/API.html_t
@@ -0,0 +1 @@
+{{ project }}-{{ version }}
diff --git a/tests/roots/test-html_extra_path/extra/css/style.css b/tests/roots/test-html_assets/extra/css/style.css
index e69de29bb..e69de29bb 100644
--- a/tests/roots/test-html_extra_path/extra/css/style.css
+++ b/tests/roots/test-html_assets/extra/css/style.css
diff --git a/tests/roots/test-html_assets/extra/rimg.png b/tests/roots/test-html_assets/extra/rimg.png
new file mode 100644
index 000000000..fda6cd29e
--- /dev/null
+++ b/tests/roots/test-html_assets/extra/rimg.png
Binary files differ
diff --git a/tests/roots/test-html_extra_path/subdir/_build/index.html b/tests/roots/test-html_assets/extra/subdir/.htaccess
index e69de29bb..e69de29bb 100644
--- a/tests/roots/test-html_extra_path/subdir/_build/index.html
+++ b/tests/roots/test-html_assets/extra/subdir/.htaccess
diff --git a/tests/roots/test-html_assets/extra/subdir/.htpasswd b/tests/roots/test-html_assets/extra/subdir/.htpasswd
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/roots/test-html_assets/extra/subdir/.htpasswd
diff --git a/tests/roots/test-html_extra_path/index.rst b/tests/roots/test-html_assets/index.rst
index 6d5619455..6d5619455 100644
--- a/tests/roots/test-html_extra_path/index.rst
+++ b/tests/roots/test-html_assets/index.rst
diff --git a/tests/roots/test-html_assets/static/.htaccess b/tests/roots/test-html_assets/static/.htaccess
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/roots/test-html_assets/static/.htaccess
diff --git a/tests/roots/test-html_assets/static/.htpasswd b/tests/roots/test-html_assets/static/.htpasswd
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/roots/test-html_assets/static/.htpasswd
diff --git a/tests/roots/test-html_assets/static/API.html_t b/tests/roots/test-html_assets/static/API.html_t
new file mode 100644
index 000000000..34ecd9df1
--- /dev/null
+++ b/tests/roots/test-html_assets/static/API.html_t
@@ -0,0 +1 @@
+{{ project }}-{{ version }}
diff --git a/tests/roots/test-html_assets/static/css/style.css b/tests/roots/test-html_assets/static/css/style.css
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/roots/test-html_assets/static/css/style.css
diff --git a/tests/roots/test-html_assets/static/rimg.png b/tests/roots/test-html_assets/static/rimg.png
new file mode 100644
index 000000000..fda6cd29e
--- /dev/null
+++ b/tests/roots/test-html_assets/static/rimg.png
Binary files differ
diff --git a/tests/roots/test-html_assets/static/subdir/.htaccess b/tests/roots/test-html_assets/static/subdir/.htaccess
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/roots/test-html_assets/static/subdir/.htaccess
diff --git a/tests/roots/test-html_assets/static/subdir/.htpasswd b/tests/roots/test-html_assets/static/subdir/.htpasswd
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/roots/test-html_assets/static/subdir/.htpasswd
diff --git a/tests/roots/test-html_assets/subdir/_build/index.html b/tests/roots/test-html_assets/subdir/_build/index.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/roots/test-html_assets/subdir/_build/index.html
diff --git a/tests/roots/test-html_assets/subdir/background.png b/tests/roots/test-html_assets/subdir/background.png
new file mode 100644
index 000000000..fda6cd29e
--- /dev/null
+++ b/tests/roots/test-html_assets/subdir/background.png
Binary files differ
diff --git a/tests/roots/test-html_extra_path/extra/rimg.png b/tests/roots/test-html_extra_path/extra/rimg.png
deleted file mode 100644
index 1081dc143..000000000
--- a/tests/roots/test-html_extra_path/extra/rimg.png
+++ /dev/null
Binary files differ
diff --git a/tests/roots/test-html_extra_path/subdir/background.png b/tests/roots/test-html_extra_path/subdir/background.png
deleted file mode 100644
index 1081dc143..000000000
--- a/tests/roots/test-html_extra_path/subdir/background.png
+++ /dev/null
Binary files differ
diff --git a/tests/roots/test-image-glob/img.ja.png b/tests/roots/test-image-glob/img.ja.png
index 4c8f89929..a97e86d66 100644
--- a/tests/roots/test-image-glob/img.ja.png
+++ b/tests/roots/test-image-glob/img.ja.png
Binary files differ
diff --git a/tests/roots/test-image-glob/img.png b/tests/roots/test-image-glob/img.png
index 4c8f89929..a97e86d66 100644
--- a/tests/roots/test-image-glob/img.png
+++ b/tests/roots/test-image-glob/img.png
Binary files differ
diff --git a/tests/roots/test-image-glob/img.zh.png b/tests/roots/test-image-glob/img.zh.png
index 4c8f89929..a97e86d66 100644
--- a/tests/roots/test-image-glob/img.zh.png
+++ b/tests/roots/test-image-glob/img.zh.png
Binary files differ
diff --git a/tests/roots/test-image-glob/rimg.png b/tests/roots/test-image-glob/rimg.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-image-glob/rimg.png
+++ b/tests/roots/test-image-glob/rimg.png
Binary files differ
diff --git a/tests/roots/test-image-glob/rimg.xx.png b/tests/roots/test-image-glob/rimg.xx.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-image-glob/rimg.xx.png
+++ b/tests/roots/test-image-glob/rimg.xx.png
Binary files differ
diff --git a/tests/roots/test-image-glob/subdir/rimg.png b/tests/roots/test-image-glob/subdir/rimg.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-image-glob/subdir/rimg.png
+++ b/tests/roots/test-image-glob/subdir/rimg.png
Binary files differ
diff --git a/tests/roots/test-image-glob/subdir/rimg.xx.png b/tests/roots/test-image-glob/subdir/rimg.xx.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-image-glob/subdir/rimg.xx.png
+++ b/tests/roots/test-image-glob/subdir/rimg.xx.png
Binary files differ
diff --git a/tests/roots/test-image-glob/testimäge.png b/tests/roots/test-image-glob/testimäge.png
index 4c8f89929..a97e86d66 100644
--- a/tests/roots/test-image-glob/testimäge.png
+++ b/tests/roots/test-image-glob/testimäge.png
Binary files differ
diff --git a/tests/roots/test-image-in-section/pic.png b/tests/roots/test-image-in-section/pic.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-image-in-section/pic.png
+++ b/tests/roots/test-image-in-section/pic.png
Binary files differ
diff --git a/tests/roots/test-intl/i18n.png b/tests/roots/test-intl/i18n.png
index 4c8f89929..a97e86d66 100644
--- a/tests/roots/test-intl/i18n.png
+++ b/tests/roots/test-intl/i18n.png
Binary files differ
diff --git a/tests/roots/test-intl/img.png b/tests/roots/test-intl/img.png
index 4c8f89929..a97e86d66 100644
--- a/tests/roots/test-intl/img.png
+++ b/tests/roots/test-intl/img.png
Binary files differ
diff --git a/tests/roots/test-numfig/rimg.png b/tests/roots/test-numfig/rimg.png
index 1081dc143..fda6cd29e 100644
--- a/tests/roots/test-numfig/rimg.png
+++ b/tests/roots/test-numfig/rimg.png
Binary files differ
diff --git a/tests/roots/test-search/index.rst b/tests/roots/test-search/index.rst
index f2536ce9a..6383d9157 100644
--- a/tests/roots/test-search/index.rst
+++ b/tests/roots/test-search/index.rst
@@ -5,4 +5,10 @@ meta keywords
:keywords lang=en: findthiskey, thistoo, notgerman
:keywords: thisonetoo
:keywords lang=de: onlygerman, onlytoogerman
- :description: thisnoteither \ No newline at end of file
+ :description: thisnoteither
+
+Stemmer
+=======
+
+zfs
+findthisstemmedkey \ No newline at end of file
diff --git a/tests/roots/test-searchadapters/conf.py b/tests/roots/test-searchadapters/conf.py
new file mode 100644
index 000000000..ade976ab5
--- /dev/null
+++ b/tests/roots/test-searchadapters/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+
+master_doc = 'markup'
+source_suffix = '.txt'
diff --git a/tests/roots/test-searchadapters/markup.txt b/tests/roots/test-searchadapters/markup.txt
new file mode 100644
index 000000000..77f245a6f
--- /dev/null
+++ b/tests/roots/test-searchadapters/markup.txt
@@ -0,0 +1,447 @@
+:tocdepth: 2
+
+.. title:: set by title directive
+
+Testing various markup
+======================
+
+Meta markup
+-----------
+
+.. sectionauthor:: Georg Brandl
+.. moduleauthor:: Georg Brandl
+
+.. contents:: TOC
+
+.. meta::
+ :author: Me
+ :keywords: docs, sphinx
+
+
+Generic reST
+------------
+
+A |subst| (the definition is in rst_epilog).
+
+.. highlight:: none
+
+.. _label:
+
+::
+
+ some code
+
+Option list:
+
+-h help
+--help also help
+
+Line block:
+
+| line1
+| line2
+| line3
+| line4
+| line5
+| line6
+| line7
+
+
+Body directives
+^^^^^^^^^^^^^^^
+
+.. topic:: Title
+
+ Topic body.
+
+.. sidebar:: Sidebar
+ :subtitle: Sidebar subtitle
+
+ Sidebar body.
+
+.. rubric:: Test rubric
+
+.. epigraph:: Epigraph title
+
+ Epigraph body.
+
+ -- Author
+
+.. highlights:: Highlights
+
+ Highlights body.
+
+.. pull-quote:: Pull-quote
+
+ Pull quote body.
+
+.. compound::
+
+ a
+
+ b
+
+.. parsed-literal::
+
+ with some *markup* inside
+
+
+.. _admonition-section:
+
+Admonitions
+^^^^^^^^^^^
+
+.. admonition:: My Admonition
+
+ Admonition text.
+
+.. note::
+ Note text.
+
+.. warning::
+
+ Warning text.
+
+.. _some-label:
+
+.. tip::
+ Tip text.
+
+Indirect hyperlink targets
+
+.. _other-label: some-label_
+
+Inline markup
+-------------
+
+*Generic inline markup*
+
+Adding \n to test unescaping.
+
+* :command:`command\\n`
+* :dfn:`dfn\\n`
+* :guilabel:`guilabel with &accelerator and \\n`
+* :kbd:`kbd\\n`
+* :mailheader:`mailheader\\n`
+* :makevar:`makevar\\n`
+* :manpage:`manpage\\n`
+* :mimetype:`mimetype\\n`
+* :newsgroup:`newsgroup\\n`
+* :program:`program\\n`
+* :regexp:`regexp\\n`
+* :menuselection:`File --> Close\\n`
+* :menuselection:`&File --> &Print`
+* :file:`a/{varpart}/b\\n`
+* :samp:`print {i}\\n`
+
+*Linking inline markup*
+
+* :pep:`8`
+* :pep:`Python Enhancement Proposal #8 <8>`
+* :rfc:`1`
+* :rfc:`Request for Comments #1 <1>`
+* :envvar:`HOME`
+* :keyword:`with`
+* :token:`try statement <try_stmt>`
+* :ref:`admonition-section`
+* :ref:`here <some-label>`
+* :ref:`there <other-label>`
+* :ref:`my-figure`
+* :ref:`my-figure-name`
+* :ref:`my-table`
+* :ref:`my-table-name`
+* :ref:`my-code-block`
+* :ref:`my-code-block-name`
+* :numref:`my-figure`
+* :numref:`my-figure-name`
+* :numref:`my-table`
+* :numref:`my-table-name`
+* :numref:`my-code-block`
+* :numref:`my-code-block-name`
+* :doc:`subdir/includes`
+* ``:download:`` is tested in includes.txt
+* :option:`Python -c option <python -c>`
+* This used to crash: :option:`&option`
+
+Test :abbr:`abbr (abbreviation)` and another :abbr:`abbr (abbreviation)`.
+
+Testing the :index:`index` role, also available with
+:index:`explicit <pair: title; explicit>` title.
+
+.. _with:
+
+With
+----
+
+(Empty section.)
+
+
+Tables
+------
+
+.. tabularcolumns:: |L|p{5cm}|R|
+
+.. _my-table:
+
+.. table:: my table
+ :name: my-table-name
+
+ +----+----------------+----+
+ | 1 | * Block elems | x |
+ | | * In table | |
+ +----+----------------+----+
+ | 2 | Empty cells: | |
+ +----+----------------+----+
+
+.. table:: empty cell in table header
+
+ ===== ======
+ \
+ ===== ======
+ 1 2
+ 3 4
+ ===== ======
+
+Tables with multirow and multicol:
+
+.. only:: latex
+
+ +----+----------------+---------+
+ | 1 | test! | c |
+ +----+---------+------+ |
+ | 2 | col | col | |
+ | y +---------+------+----+----+
+ | x | multi-column cell | x |
+ +----+---------------------+----+
+
+ +----+
+ | 1 |
+ + +
+ | |
+ +----+
+
+.. list-table::
+ :header-rows: 0
+
+ * - .. figure:: img.png
+
+ figure in table
+
+
+Figures
+-------
+
+.. _my-figure:
+
+.. figure:: img.png
+ :name: my-figure-name
+
+ My caption of the figure
+
+ My description paragraph of the figure.
+
+ Description paragraph is wraped with legend node.
+
+.. figure:: rimg.png
+ :align: right
+
+ figure with align option
+
+.. figure:: rimg.png
+ :align: right
+ :figwidth: 50%
+
+ figure with align & figwidth option
+
+.. figure:: rimg.png
+ :align: right
+ :width: 3cm
+
+ figure with align & width option
+
+Version markup
+--------------
+
+.. versionadded:: 0.6
+ Some funny **stuff**.
+
+.. versionchanged:: 0.6
+ Even more funny stuff.
+
+.. deprecated:: 0.6
+ Boring stuff.
+
+.. versionadded:: 1.2
+
+ First paragraph of versionadded.
+
+.. versionchanged:: 1.2
+ First paragraph of versionchanged.
+
+ Second paragraph of versionchanged.
+
+
+Code blocks
+-----------
+
+.. _my-code-block:
+
+.. code-block:: ruby
+ :linenos:
+ :caption: my ruby code
+ :name: my-code-block-name
+
+ def ruby?
+ false
+ end
+
+.. code-block:: c
+
+ import sys
+
+ sys.stdout.write('hello world!\n')
+
+
+Misc stuff
+----------
+
+Stuff [#]_
+
+Reference lookup: [Ref1]_ (defined in another file).
+Reference lookup underscore: [Ref_1]_
+
+.. seealso:: something, something else, something more
+
+ `Google <http://www.google.com>`_
+ For everything.
+
+.. hlist::
+ :columns: 4
+
+ * This
+ * is
+ * a horizontal
+ * list
+ * with several
+ * items
+
+.. rubric:: Side note
+
+This is a side note.
+
+This tests :CLASS:`role names in uppercase`.
+
+.. centered:: LICENSE AGREEMENT
+
+.. acks::
+
+ * Terry Pratchett
+ * J. R. R. Tolkien
+ * Monty Python
+
+.. glossary::
+ :sorted:
+
+ boson
+ Particle with integer spin.
+
+ *fermion*
+ Particle with half-integer spin.
+
+ tauon
+ myon
+ electron
+ Examples for fermions.
+
+ über
+ Gewisse
+
+ änhlich
+ Dinge
+
+.. productionlist::
+ try_stmt: `try1_stmt` | `try2_stmt`
+ try1_stmt: "try" ":" `suite`
+ : ("except" [`expression` ["," `target`]] ":" `suite`)+
+ : ["else" ":" `suite`]
+ : ["finally" ":" `suite`]
+ try2_stmt: "try" ":" `suite`
+ : "finally" ":" `suite`
+
+
+Index markup
+------------
+
+.. index::
+ single: entry
+ pair: entry; pair
+ double: entry; double
+ triple: index; entry; triple
+ keyword: with
+ see: from; to
+ seealso: fromalso; toalso
+
+Invalid index markup...
+
+.. index::
+ single:
+ pair:
+ keyword:
+
+.. index::
+ !Main, !Other
+ !single: entry; pair
+
+:index:`!Main`
+
+.. _ölabel:
+
+Ö... Some strange characters
+----------------------------
+
+Testing öäü...
+
+
+Only directive
+--------------
+
+.. only:: html
+
+ In HTML.
+
+.. only:: latex
+
+ In LaTeX.
+
+.. only:: html or latex
+
+ In both.
+
+.. only:: confpytag and (testtag or nonexisting_tag)
+
+ Always present, because set through conf.py/command line.
+
+
+Any role
+--------
+
+.. default-role:: any
+
+Test referencing to `headings <with>` and `objects <func_without_body>`.
+Also `modules <mod>` and `classes <Time>`.
+
+More domains:
+
+* `JS <bar.baz>`
+* `C <SphinxType>`
+* `myobj` (user markup)
+* `n::Array`
+* `perl -c`
+
+.. default-role::
+
+
+.. rubric:: Footnotes
+
+.. [#] Like footnotes.
+
diff --git a/tests/roots/test-warnings/autodoc_fodder.py b/tests/roots/test-warnings/autodoc_fodder.py
new file mode 100644
index 000000000..e5fd74139
--- /dev/null
+++ b/tests/roots/test-warnings/autodoc_fodder.py
@@ -0,0 +1,7 @@
+
+class MarkupError(object):
+ """
+ .. note:: This is a docstring with a
+ small markup error which should have
+ correct location information.
+ """
diff --git a/tests/roots/test-warnings/conf.py b/tests/roots/test-warnings/conf.py
new file mode 100644
index 000000000..9fbcab199
--- /dev/null
+++ b/tests/roots/test-warnings/conf.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+
+import os
+import sys
+sys.path.append(os.path.abspath('.'))
+
+master_doc = 'index'
+extensions = ['sphinx.ext.autodoc']
+
+latex_documents = [
+ (master_doc, 'test.tex', 'test-warnings', 'Sphinx', 'report')
+]
diff --git a/tests/roots/test-warnings/index.rst b/tests/roots/test-warnings/index.rst
new file mode 100644
index 000000000..bef44cb4f
--- /dev/null
+++ b/tests/roots/test-warnings/index.rst
@@ -0,0 +1,48 @@
+test-warnings
+=============
+
+.. automodule:: autodoc_fodder
+ :noindex:
+
+ .. autoclass:: MarkupError
+
+.. a non-existing image with direct filename
+.. image:: foo.png
+
+.. a non-existing image with .*
+.. image:: foo.*
+
+.. an SVG image (for HTML at least)
+.. image:: svgimg.*
+
+.. a non-local image URI
+.. image:: http://www.python.org/logo.png
+
+.. should give a warning
+.. literalinclude:: wrongenc.inc
+ :language: none
+
+.. a non-existing download
+
+Don't download :download:`this <nonexisting.png>`.
+
+.. Invalid index markup
+.. index::
+ single:
+ pair:
+ keyword:
+
+.. Invalid code-block
+.. code-block:: c
+
+ import sys
+
+ sys.stdout.write('hello world!\n')
+
+.. unknown option
+
+This used to crash: :option:`&option`
+
+.. missing citation
+
+[missing]_ citation
diff --git a/tests/roots/test-warnings/svgimg.pdf b/tests/roots/test-warnings/svgimg.pdf
new file mode 100644
index 000000000..cacbd855d
--- /dev/null
+++ b/tests/roots/test-warnings/svgimg.pdf
Binary files differ
diff --git a/tests/roots/test-warnings/svgimg.svg b/tests/roots/test-warnings/svgimg.svg
new file mode 100644
index 000000000..10e035b6d
--- /dev/null
+++ b/tests/roots/test-warnings/svgimg.svg
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ height="60"
+ width="60"
+ _SVGFile__filename="oldscale/apps/warning.svg"
+ version="1.0"
+ y="0"
+ x="0"
+ id="svg1"
+ sodipodi:version="0.32"
+ inkscape:version="0.41"
+ sodipodi:docname="exclamation.svg"
+ sodipodi:docbase="/home/danny/work/icons/primary/scalable/actions">
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0000000"
+ inkscape:pageshadow="2"
+ inkscape:zoom="7.5136000"
+ inkscape:cx="42.825186"
+ inkscape:cy="24.316071"
+ inkscape:window-width="1020"
+ inkscape:window-height="691"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:current-layer="svg1" />
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient1160">
+ <stop
+ style="stop-color: #000000;stop-opacity: 1.0;"
+ id="stop1161"
+ offset="0" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ id="stop1162"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ xlink:href="#linearGradient1160"
+ id="linearGradient1163" />
+ </defs>
+ <metadata
+ id="metadata12">
+ <RDF
+ id="RDF13">
+ <Work
+ about=""
+ id="Work14">
+ <title
+ id="title15">Part of the Flat Icon Collection (Thu Aug 26 14:31:40 2004)</title>
+ <description
+ id="description17" />
+ <subject
+ id="subject18">
+ <Bag
+ id="Bag19">
+ <li
+ id="li20" />
+ </Bag>
+ </subject>
+ <publisher
+ id="publisher21">
+ <Agent
+ about=""
+ id="Agent22">
+ <title
+ id="title23" />
+ </Agent>
+ </publisher>
+ <creator
+ id="creator24">
+ <Agent
+ about=""
+ id="Agent25">
+ <title
+ id="title26">Danny Allen</title>
+ </Agent>
+ </creator>
+ <rights
+ id="rights28">
+ <Agent
+ about=""
+ id="Agent29">
+ <title
+ id="title30">Danny Allen</title>
+ </Agent>
+ </rights>
+ <date
+ id="date32" />
+ <format
+ id="format33">image/svg+xml</format>
+ <type
+ id="type35"
+ resource="http://purl.org/dc/dcmitype/StillImage" />
+ <license
+ id="license36"
+ resource="http://creativecommons.org/licenses/LGPL/2.1/">
+ <date
+ id="date37" />
+ </license>
+ <language
+ id="language38">en</language>
+ </Work>
+ </RDF>
+ <rdf:RDF
+ id="RDF40">
+ <cc:Work
+ rdf:about=""
+ id="Work41">
+ <dc:format
+ id="format42">image/svg+xml</dc:format>
+ <dc:type
+ id="type44"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="g2099">
+ <path
+ style="color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:8.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+ d="M 55.311891,51.920745 L 4.6880989,51.920744 L 29.999995,8.0792542 L 55.311891,51.920745 z "
+ id="path1724" />
+ <path
+ style="color:#000000;fill:#ffe940;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1250010;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+ d="M 55.311891,51.920745 L 4.6880989,51.920744 L 29.999995,8.0792542 L 55.311891,51.920745 z "
+ id="path1722" />
+ <path
+ style="font-size:12.000000;font-weight:900;fill:none;fill-opacity:1.0000000;stroke:#ffffff;stroke-width:8.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 34.944960,10.779626 L 34.944960,33.186510 C 34.944960,34.752415 34.501979,36.081368 33.616007,37.173380 C 32.750636,38.265402 31.545298,38.811408 29.999995,38.811408 C 28.475302,38.811408 27.269965,38.265402 26.383993,37.173380 C 25.498020,36.060767 25.055030,34.731804 25.055030,33.186510 L 25.055030,10.779626 C 25.055030,9.1931155 25.498020,7.8641562 26.383993,6.7927462 C 27.269965,5.7007332 28.475302,5.1547262 29.999995,5.1547262 C 31.009593,5.1547262 31.885265,5.4019740 32.627010,5.8964706 C 33.389356,6.3909681 33.966274,7.0709005 34.357752,7.9362696 C 34.749221,8.7810349 34.944960,9.7288200 34.944960,10.779626 z "
+ id="path1099" />
+ <path
+ style="font-size:12.000000;font-weight:900;fill:#e71c02;fill-opacity:1.0000000;stroke:none;stroke-width:3.1249981;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1.0000000"
+ d="M 29.999995,3.5986440 C 28.102272,3.5986440 26.318514,4.3848272 25.156245,5.8173940 C 24.028906,7.1806889 23.499995,8.9087770 23.499995,10.786144 L 23.499995,33.192394 C 23.499995,35.036302 24.050685,36.772771 25.156245,38.161144 C 26.318514,39.593721 28.102273,40.379893 29.999995,40.379894 C 31.913354,40.379894 33.697195,39.576736 34.843745,38.129894 C 35.959941,36.754118 36.499995,35.052976 36.499995,33.192394 L 36.499995,10.786144 C 36.499995,9.5413010 36.276626,8.3551469 35.781245,7.2861440 C 35.278844,6.1755772 34.477762,5.2531440 33.468745,4.5986440 C 32.454761,3.9226545 31.264694,3.5986439 29.999995,3.5986440 z "
+ id="path835"
+ sodipodi:nodetypes="cccccccccccc" />
+ <path
+ style="color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:5.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+ d="M 36.506243,49.901522 C 36.506243,53.492972 33.591442,56.407773 29.999991,56.407773 C 26.408541,56.407773 23.493739,53.492972 23.493739,49.901522 C 23.493739,46.310071 26.408541,43.395270 29.999991,43.395270 C 33.591442,43.395270 36.506243,46.310071 36.506243,49.901522 z "
+ id="path1727" />
+ <path
+ style="color:#000000;fill:#e71c02;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:3.1250000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none"
+ d="M 36.506243,49.901522 C 36.506243,53.492972 33.591442,56.407773 29.999991,56.407773 C 26.408541,56.407773 23.493739,53.492972 23.493739,49.901522 C 23.493739,46.310071 26.408541,43.395270 29.999991,43.395270 C 33.591442,43.395270 36.506243,46.310071 36.506243,49.901522 z "
+ id="path1725" />
+ </g>
+</svg>
diff --git a/tests/root/undecodable.txt b/tests/roots/test-warnings/undecodable.rst
index a4cf5c370..a4cf5c370 100644
--- a/tests/root/undecodable.txt
+++ b/tests/roots/test-warnings/undecodable.rst
diff --git a/tests/roots/test-warnings/wrongenc.inc b/tests/roots/test-warnings/wrongenc.inc
new file mode 100644
index 000000000..700f61344
--- /dev/null
+++ b/tests/roots/test-warnings/wrongenc.inc
@@ -0,0 +1,3 @@
+This file is encoded in latin-1 but at first read as utf-8.
+
+Max Strauß aß in München eine Leberkässemmel.
diff --git a/tests/run.py b/tests/run.py
index b4bbf9822..7b750ca92 100755
--- a/tests/run.py
+++ b/tests/run.py
@@ -16,6 +16,7 @@ import sys
import traceback
from path import path
+import nose
testroot = os.path.dirname(__file__) or '.'
sys.path.insert(0, os.path.abspath(os.path.join(testroot, os.path.pardir)))
@@ -23,7 +24,7 @@ sys.path.insert(0, os.path.abspath(os.path.join(testroot, os.path.pardir)))
# check dependencies before testing
print('Checking dependencies...')
for modname in ('nose', 'mock', 'six', 'docutils', 'jinja2', 'pygments',
- 'snowballstemmer', 'babel'):
+ 'snowballstemmer', 'babel', 'html5lib'):
try:
__import__(modname)
except ImportError as err:
@@ -47,5 +48,4 @@ tempdir.makedirs()
print('Running Sphinx test suite (with Python %s)...' % sys.version.split()[0])
sys.stdout.flush()
-import nose
nose.main()
diff --git a/tests/test_api_translator.py b/tests/test_api_translator.py
index 8f0f88a1d..e8cfcb458 100644
--- a/tests/test_api_translator.py
+++ b/tests/test_api_translator.py
@@ -67,7 +67,7 @@ def test_html_with_set_translator_for_html_and_html_translator_class(
assert translator_class.__name__ == 'ConfHTMLTranslator'
-## this test break test_websupport.test_comments test. why?
+# this test break test_websupport.test_comments test. why?
# @with_app(
# buildername='dirhtml',
# srcdir=(test_roots / 'test-api-set-translator'),
diff --git a/tests/test_application.py b/tests/test_application.py
index 7bc970c9d..ad4f84870 100644
--- a/tests/test_application.py
+++ b/tests/test_application.py
@@ -14,7 +14,7 @@ from docutils import nodes
from sphinx.application import ExtensionError
from sphinx.domains import Domain
-from util import with_app, raises_msg
+from util import with_app, raises_msg, strip_escseq
@with_app()
@@ -60,14 +60,21 @@ def test_output(app, status, warning):
old_count = app._warncount
app.warn("Bad news!")
- assert warning.getvalue() == "WARNING: Bad news!\n"
+ assert strip_escseq(warning.getvalue()) == "WARNING: Bad news!\n"
assert app._warncount == old_count + 1
@with_app()
def test_extensions(app, status, warning):
app.setup_extension('shutil')
- assert warning.getvalue().startswith("WARNING: extension 'shutil'")
+ assert strip_escseq(warning.getvalue()).startswith("WARNING: extension 'shutil'")
+
+
+@with_app()
+def test_extension_in_blacklist(app, status, warning):
+ app.setup_extension('sphinxjp.themecore')
+ msg = strip_escseq(warning.getvalue())
+ assert msg.startswith("WARNING: the extension 'sphinxjp.themecore' was")
@with_app()
diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py
index 183484846..fca3c2b9e 100644
--- a/tests/test_autodoc.py
+++ b/tests/test_autodoc.py
@@ -11,7 +11,7 @@
"""
# "raises" imported for usage by autodoc
-from util import TestApp, Struct, raises, SkipTest
+from util import TestApp, Struct, raises, SkipTest # NOQA
from nose.tools import with_setup, eq_
from six import StringIO
@@ -22,6 +22,7 @@ from sphinx.ext.autodoc import AutoDirective, add_documenter, \
app = None
+
def setup_module():
global app
app = TestApp()
@@ -38,6 +39,7 @@ def teardown_module():
directive = options = None
+
def setup_test():
global options, directive
global processed_docstrings, processed_signatures, _warnings
@@ -73,19 +75,19 @@ def setup_test():
_warnings = []
+processed_docstrings = []
+processed_signatures = []
+
def warnfunc(msg):
_warnings.append(msg)
-processed_docstrings = []
-
def process_docstring(app, what, name, obj, options, lines):
processed_docstrings.append((what, name))
if name == 'bar':
lines.extend(['42', ''])
-processed_signatures = []
def process_signature(app, what, name, obj, options, args, retann):
processed_signatures.append((what, name))
@@ -164,25 +166,28 @@ def test_format_signature():
# test for functions
def f(a, b, c=1, **d):
pass
+
def g(a='\n'):
pass
assert formatsig('function', 'f', f, None, None) == '(a, b, c=1, **d)'
assert formatsig('function', 'f', f, 'a, b, c, d', None) == '(a, b, c, d)'
- assert formatsig('function', 'f', f, None, 'None') == \
- '(a, b, c=1, **d) -> None'
+ assert formatsig('function', 'f', f, None, 'None') == '(a, b, c=1, **d) -> None'
assert formatsig('function', 'g', g, None, None) == r"(a='\\n')"
# test for classes
class D:
pass
+
class E(object):
pass
# no signature for classes without __init__
for C in (D, E):
assert formatsig('class', 'D', C, None, None) == ''
+
class F:
def __init__(self, a, b=None):
pass
+
class G(F, object):
pass
for C in (F, G):
@@ -191,6 +196,7 @@ def test_format_signature():
# __init__ have signature at first line of docstring
directive.env.config.autoclass_content = 'both'
+
class F2:
'''some docstring for F2.'''
def __init__(self, *args, **kw):
@@ -211,8 +217,10 @@ def test_format_signature():
class H:
def foo1(self, b, *c):
pass
+
def foo2(b, *c):
pass
+
def foo3(self, d='\n'):
pass
assert formatsig('method', 'H.foo', H.foo1, None, None) == '(b, *c)'
@@ -431,6 +439,7 @@ def test_docstring_processing():
lid = app.connect('autodoc-process-docstring',
cut_lines(1, 1, ['function']))
+
def f():
"""
first line
@@ -441,6 +450,7 @@ def test_docstring_processing():
app.disconnect(lid)
lid = app.connect('autodoc-process-docstring', between('---', ['function']))
+
def g():
"""
first line
@@ -452,8 +462,9 @@ def test_docstring_processing():
assert process('function', 'g', g) == ['second line', '']
app.disconnect(lid)
- lid = app.connect('autodoc-process-docstring', between('---', ['function'],
- exclude=True))
+ lid = app.connect('autodoc-process-docstring',
+ between('---', ['function'], exclude=True))
+
def h():
"""
first line
@@ -522,7 +533,7 @@ def test_new_documenter():
def assert_result_contains(item, objtype, name, **kw):
inst = AutoDirective._registry[objtype](directive, name)
inst.generate(**kw)
- #print '\n'.join(directive.result)
+ # print '\n'.join(directive.result)
assert len(_warnings) == 0, _warnings
assert item in directive.result
del directive.result[:]
@@ -535,6 +546,7 @@ def test_new_documenter():
def test_attrgetter_using():
def assert_getter_works(objtype, name, obj, attrs=[], **kw):
getattr_spy = []
+
def special_getattr(obj, name, *defargs):
if name in attrs:
getattr_spy.append((obj, name))
@@ -556,12 +568,10 @@ def test_attrgetter_using():
options.members = ALL
options.inherited_members = False
- assert_getter_works('class', 'test_autodoc.Class', Class,
- ['meth'])
+ assert_getter_works('class', 'test_autodoc.Class', Class, ['meth'])
options.inherited_members = True
- assert_getter_works('class', 'test_autodoc.Class', Class,
- ['meth', 'inheritedmeth'])
+ assert_getter_works('class', 'test_autodoc.Class', Class, ['meth', 'inheritedmeth'])
@with_setup(setup_test)
@@ -578,7 +588,7 @@ def test_generate():
inst = AutoDirective._registry[objtype](directive, name)
inst.generate(**kw)
assert directive.result
- #print '\n'.join(directive.result)
+ # print '\n'.join(directive.result)
assert len(_warnings) == 0, _warnings
del directive.result[:]
@@ -586,13 +596,12 @@ def test_generate():
del processed_docstrings[:]
del processed_signatures[:]
assert_works(objtype, name, **kw)
- assert set(processed_docstrings) | set(processed_signatures) == \
- set(items)
+ assert set(processed_docstrings) | set(processed_signatures) == set(items)
def assert_result_contains(item, objtype, name, **kw):
inst = AutoDirective._registry[objtype](directive, name)
inst.generate(**kw)
- #print '\n'.join(directive.result)
+ # print '\n'.join(directive.result)
assert len(_warnings) == 0, _warnings
assert item in directive.result
del directive.result[:]
@@ -604,17 +613,17 @@ def test_generate():
assert len(_warnings) == 0, _warnings
items = list(reversed(items))
lineiter = iter(directive.result)
- #for line in directive.result:
- # if line.strip():
- # print repr(line)
+ # for line in directive.result:
+ # if line.strip():
+ # print repr(line)
while items:
item = items.pop()
for line in lineiter:
if line == item:
break
else: # ran out of items!
- assert False, 'item %r not found in result or not in the ' \
- ' correct order' % item
+ assert False, ('item %r not found in result or not in the '
+ ' correct order' % item)
del directive.result[:]
options.members = []
@@ -824,19 +833,19 @@ def test_generate():
'module', 'test_autodoc')
# --- generate fodder ------------
-import six, sys
-
__all__ = ['Class']
#: documentation for the integer
integer = 1
+
class CustomEx(Exception):
"""My custom exception."""
def f(self):
"""Exception method."""
+
class CustomDataDescriptor(object):
"""Descriptor class docstring."""
@@ -852,6 +861,7 @@ class CustomDataDescriptor(object):
"""Function."""
return "The Answer"
+
def _funky_classmethod(name, b, c, d, docstring=None):
"""Generates a classmethod for a class from a template by filling out
some arguments."""
@@ -863,6 +873,7 @@ def _funky_classmethod(name, b, c, d, docstring=None):
function.__doc__ = docstring
return classmethod(function)
+
class Base(object):
def inheritedmeth(self):
"""Inherited function."""
@@ -908,10 +919,10 @@ class Class(Base):
roger = _funky_classmethod("roger", 2, 3, 4)
moore = _funky_classmethod("moore", 9, 8, 7,
- docstring="moore(a, e, f) -> happiness")
+ docstring="moore(a, e, f) -> happiness")
def __init__(self, arg):
- self.inst_attr_inline = None #: an inline documented instance attr
+ self.inst_attr_inline = None #: an inline documented instance attr
#: a documented instance attribute
self.inst_attr_comment = None
self.inst_attr_string = None
@@ -928,6 +939,7 @@ class Class(Base):
class CustomDict(dict):
"""Docstring."""
+
def function(foo, *args, **kwds):
"""
Return spam.
@@ -977,14 +989,17 @@ First line of docstring
"""
return 456
+
class StrRepr(str):
def __repr__(self):
return self
+
class AttCls(object):
a1 = StrRepr('hello\nworld')
a2 = None
+
class InstAttCls(object):
"""Class with documented class and instance attributes."""
@@ -1010,7 +1025,7 @@ def test_type_hints():
from sphinx.util.inspect import getargspec
try:
- from typing_test_data import f0, f1, f2, f3, f4, f5, f6, f7, f8
+ from typing_test_data import f0, f1, f2, f3, f4, f5, f6, f7, f8, f9
except (ImportError, SyntaxError):
raise SkipTest('Cannot import Python code with function annotations')
@@ -1046,3 +1061,6 @@ def test_type_hints():
# Tuple types
verify_arg_spec(f8, '(x: typing.Tuple[int, str],'
' y: typing.Tuple[int, ...]) -> None')
+
+ # Instance annotations
+ verify_arg_spec(f9, '(x: CustomAnnotation, y: 123) -> None')
diff --git a/tests/test_autodoc_py35.py b/tests/test_autodoc_py35.py
index 9bacc3d65..43cda2260 100644
--- a/tests/test_autodoc_py35.py
+++ b/tests/test_autodoc_py35.py
@@ -11,6 +11,8 @@
"""
# "raises" imported for usage by autodoc
+import six
+import sys
from util import TestApp, Struct, raises, SkipTest
from nose.tools import with_setup, eq_
@@ -22,6 +24,7 @@ from sphinx.ext.autodoc import AutoDirective, add_documenter, \
app = None
+
def setup_module():
global app
app = TestApp()
@@ -38,6 +41,7 @@ def teardown_module():
directive = options = None
+
def setup_test():
global options, directive
global processed_docstrings, processed_signatures, _warnings
@@ -73,19 +77,19 @@ def setup_test():
_warnings = []
+processed_docstrings = []
+processed_signatures = []
+
def warnfunc(msg):
_warnings.append(msg)
-processed_docstrings = []
-
def process_docstring(app, what, name, obj, options, lines):
processed_docstrings.append((what, name))
if name == 'bar':
lines.extend(['42', ''])
-processed_signatures = []
def process_signature(app, what, name, obj, options, args, retann):
processed_signatures.append((what, name))
@@ -116,7 +120,7 @@ def test_generate():
inst = AutoDirective._registry[objtype](directive, name)
inst.generate(**kw)
assert directive.result
- #print '\n'.join(directive.result)
+ # print '\n'.join(directive.result)
assert len(_warnings) == 0, _warnings
del directive.result[:]
@@ -124,13 +128,12 @@ def test_generate():
del processed_docstrings[:]
del processed_signatures[:]
assert_works(objtype, name, **kw)
- assert set(processed_docstrings) | set(processed_signatures) == \
- set(items)
+ assert set(processed_docstrings) | set(processed_signatures) == set(items)
def assert_result_contains(item, objtype, name, **kw):
inst = AutoDirective._registry[objtype](directive, name)
inst.generate(**kw)
- #print '\n'.join(directive.result)
+ # print '\n'.join(directive.result)
assert len(_warnings) == 0, _warnings
assert item in directive.result
del directive.result[:]
@@ -142,17 +145,17 @@ def test_generate():
assert len(_warnings) == 0, _warnings
items = list(reversed(items))
lineiter = iter(directive.result)
- #for line in directive.result:
- # if line.strip():
- # print repr(line)
+ # for line in directive.result:
+ # if line.strip():
+ # print repr(line)
while items:
item = items.pop()
for line in lineiter:
if line == item:
break
else: # ran out of items!
- assert False, 'item %r not found in result or not in the ' \
- ' correct order' % item
+ assert False, ('item %r not found in result or not in the '
+ ' correct order' % item)
del directive.result[:]
options.members = []
@@ -233,19 +236,19 @@ def test_generate():
# --- generate fodder ------------
-import six, sys
-
__all__ = ['Class']
#: documentation for the integer
integer = 1
+
class CustomEx(Exception):
"""My custom exception."""
def f(self):
"""Exception method."""
+
class CustomDataDescriptor(object):
"""Descriptor class docstring."""
@@ -261,6 +264,7 @@ class CustomDataDescriptor(object):
"""Function."""
return "The Answer"
+
def _funky_classmethod(name, b, c, d, docstring=None):
"""Generates a classmethod for a class from a template by filling out
some arguments."""
@@ -272,6 +276,7 @@ def _funky_classmethod(name, b, c, d, docstring=None):
function.__doc__ = docstring
return classmethod(function)
+
class Base(object):
def inheritedmeth(self):
"""Inherited function."""
@@ -322,10 +327,10 @@ class Class(Base):
roger = _funky_classmethod("roger", 2, 3, 4)
moore = _funky_classmethod("moore", 9, 8, 7,
- docstring="moore(a, e, f) -> happiness")
+ docstring="moore(a, e, f) -> happiness")
def __init__(self, arg):
- self.inst_attr_inline = None #: an inline documented instance attr
+ self.inst_attr_inline = None #: an inline documented instance attr
#: a documented instance attribute
self.inst_attr_comment = None
self.inst_attr_string = None
diff --git a/tests/test_build.py b/tests/test_build.py
index 1c0d55e1b..507a1cab3 100644
--- a/tests/test_build.py
+++ b/tests/test_build.py
@@ -15,8 +15,9 @@ import pickle
from docutils import nodes
from textwrap import dedent
from sphinx.errors import SphinxError
+import sphinx.builders.linkcheck
-from util import with_app, rootdir, tempdir, SkipTest, TestApp
+from util import with_app, with_tempdir, rootdir, tempdir, SkipTest, TestApp
try:
from docutils.writers.manpage import Writer as ManWriter
@@ -31,7 +32,6 @@ class MockOpener(object):
url = req.url
return result()
-import sphinx.builders.linkcheck
sphinx.builders.linkcheck.opener = MockOpener()
@@ -76,16 +76,19 @@ def test_build_all():
yield verify_build, buildername, srcdir
-@with_app(buildername='text')
-def test_master_doc_not_found(app, status, warning):
- (app.srcdir / 'contents.txt').move(app.srcdir / 'contents.txt.bak')
+@with_tempdir
+def test_master_doc_not_found(tmpdir):
+ (tmpdir / 'conf.py').write_text('master_doc = "index"')
+ assert tmpdir.listdir() == ['conf.py']
+
try:
+ app = TestApp(buildername='dummy', srcdir=tmpdir)
app.builder.build_all()
assert False # SphinxError not raised
except Exception as exc:
assert isinstance(exc, SphinxError)
finally:
- (app.srcdir / 'contents.txt.bak').move(app.srcdir / 'contents.txt')
+ app.cleanup()
@with_app(buildername='text', testroot='circular')
diff --git a/tests/test_build_applehelp.py b/tests/test_build_applehelp.py
index 66b24e1bd..63bb0ec89 100644
--- a/tests/test_build_applehelp.py
+++ b/tests/test_build_applehelp.py
@@ -11,7 +11,6 @@
:license: BSD, see LICENSE for details.
"""
-import os
import plistlib
from util import with_app
@@ -44,8 +43,12 @@ def check_localization(outdir):
assert (lprojdir / 'localized.txt').isfile()
-@with_app(buildername='applehelp')
+@with_app(buildername='applehelp', testroot='basic', srcdir='applehelp_output',
+ confoverrides={'applehelp_bundle_id': 'org.sphinx-doc.Sphinx.help',
+ 'applehelp_disable_external_tools': True})
def test_applehelp_output(app, status, warning):
+ (app.srcdir / 'en.lproj').makedirs()
+ (app.srcdir / 'en.lproj' / 'localized.txt').write_text('')
app.builder.build_all()
# Have to use bundle_path, not outdir, because we alter the latter
diff --git a/tests/test_build_gettext.py b/tests/test_build_gettext.py
index 22fec975e..2dc62b838 100644
--- a/tests/test_build_gettext.py
+++ b/tests/test_build_gettext.py
@@ -114,7 +114,7 @@ def test_gettext_index_entries(app, status, warning):
"Exception",
"Statement",
"Builtin",
- ]
+ ]
for expect in expected_msgids:
assert expect in msgids
msgids.remove(expect)
diff --git a/tests/test_build_html.py b/tests/test_build_html.py
index 87ea8c595..085ba5067 100644
--- a/tests/test_build_html.py
+++ b/tests/test_build_html.py
@@ -13,34 +13,37 @@ import os
import re
from six import PY3, iteritems
-from six.moves import html_entities
from sphinx import __display_version__
-from util import remove_unicode_literals, gen_with_app, with_app
-from etree13 import ElementTree as ET
+from util import remove_unicode_literals, gen_with_app, with_app, strip_escseq
+from etree13 import ElementTree
+from html5lib import getTreeBuilder, HTMLParser
+TREE_BUILDER = getTreeBuilder('etree', implementation=ElementTree)
+HTML_PARSER = HTMLParser(TREE_BUILDER, namespaceHTMLElements=False)
+
ENV_WARNINGS = """\
-(%(root)s/autodoc_fodder.py:docstring of autodoc_fodder\\.MarkupError:2: \
-WARNING: Explicit markup ends without a blank line; unexpected \
-unindent\\.\\n?
-)?%(root)s/images.txt:9: WARNING: image file not readable: foo.png
-%(root)s/images.txt:23: WARNING: nonlocal image URI found: \
-http://www.python.org/logo.png
-%(root)s/includes.txt:\\d*: WARNING: Encoding 'utf-8-sig' used for \
-reading included file u'.*?wrongenc.inc' seems to be wrong, try giving an \
-:encoding: option\\n?
-%(root)s/includes.txt:4: WARNING: download file not readable: .*?nonexisting.png
-(%(root)s/markup.txt:373: WARNING: invalid single index entry u'')?
-(%(root)s/undecodable.txt:3: WARNING: undecodable source characters, replacing \
+(%(root)s/autodoc_fodder.py:docstring of autodoc_fodder.MarkupError:\\d+: \
+WARNING: duplicate object description of autodoc_fodder.MarkupError, other \
+instance in %(root)s/autodoc.rst, use :noindex: for one of them
+)?%(root)s/autodoc_fodder.py:docstring of autodoc_fodder.MarkupError:\\d+: \
+WARNING: Explicit markup ends without a blank line; unexpected unindent.
+%(root)s/index.rst:\\d+: WARNING: Encoding 'utf-8-sig' used for reading included \
+file u'%(root)s/wrongenc.inc' seems to be wrong, try giving an :encoding: option
+%(root)s/index.rst:\\d+: WARNING: image file not readable: foo.png
+%(root)s/index.rst:\\d+: WARNING: nonlocal image URI found: http://www.python.org/logo.png
+%(root)s/index.rst:\\d+: WARNING: download file not readable: %(root)s/nonexisting.png
+%(root)s/index.rst:\\d+: WARNING: invalid single index entry u''
+%(root)s/undecodable.rst:\\d+: WARNING: undecodable source characters, replacing \
with "\\?": b?'here: >>>(\\\\|/)xbb<<<'
-)?"""
+"""
HTML_WARNINGS = ENV_WARNINGS + """\
-%(root)s/images.txt:20: WARNING: no matching candidate for image URI u'foo.\\*'
-%(root)s/markup.txt:285: WARNING: Could not lex literal_block as "c". Highlighting skipped.
-%(root)s/footnote.txt:60: WARNING: citation not found: missing
-%(root)s/markup.txt:164: WARNING: unknown option: &option
+%(root)s/index.rst:\\d+: WARNING: no matching candidate for image URI u'foo.\\*'
+%(root)s/index.rst:\\d+: WARNING: Could not lex literal_block as "c". Highlighting skipped.
+%(root)s/index.rst:\\d+: WARNING: unknown option: &option
+%(root)s/index.rst:\\d+: WARNING: citation not found: missing
"""
if PY3:
@@ -65,6 +68,7 @@ HTML_XPATH = {
(".//img[@src='_images/img1.png']", ''),
(".//img[@src='_images/simg.png']", ''),
(".//img[@src='_images/svgimg.svg']", ''),
+ (".//a[@href='_sources/images.txt']", ''),
],
'subdir/images.html': [
(".//img[@src='../_images/img1.png']", ''),
@@ -174,7 +178,7 @@ HTML_XPATH = {
# ``seealso`` directive
(".//div/p[@class='first admonition-title']", 'See also'),
# a ``hlist`` directive
- (".//table[@class='hlist']/tr/td/ul/li", '^This$'),
+ (".//table[@class='hlist']/tbody/tr/td/ul/li", '^This$'),
# a ``centered`` directive
(".//p[@class='centered']/strong", 'LICENSE'),
# a glossary
@@ -203,6 +207,7 @@ HTML_XPATH = {
# docfields
(".//a[@class='reference internal'][@href='#TimeInt']/em", 'TimeInt'),
(".//a[@class='reference internal'][@href='#Time']", 'Time'),
+ (".//a[@class='reference internal'][@href='#errmod.Error']/strong", 'Error'),
# C references
(".//span[@class='pre']", 'CFunction()'),
(".//a[@href='#c.Sphinx_DoSomething']", ''),
@@ -315,25 +320,11 @@ HTML_XPATH = {
],
'otherext.html': [
(".//h1", "Generated section"),
+ (".//a[@href='_sources/otherext.foo.txt']", ''),
]
}
-class NslessParser(ET.XMLParser):
- """XMLParser that throws away namespaces in tag names."""
-
- def _fixname(self, key):
- try:
- return self._names[key]
- except KeyError:
- name = key
- br = name.find('}')
- if br > 0:
- name = name[br+1:]
- self._names[key] = name = self._fixtext(name)
- return name
-
-
def check_xpath(etree, fname, path, check, be_found=True):
nodes = list(etree.findall(path))
if check is None:
@@ -391,12 +382,10 @@ def check_extra_entries(outdir):
assert (outdir / 'robots.txt').isfile()
-@gen_with_app(buildername='html', freshenv=True, # use freshenv to check warnings
- confoverrides={'html_context.hckey_co': 'hcval_co'},
- tags=['testtag'])
-def test_html_output(app, status, warning):
+@with_app(buildername='html', testroot='warnings', freshenv=True)
+def test_html_warnings(app, status, warning):
app.builder.build_all()
- html_warnings = warning.getvalue().replace(os.sep, '/')
+ html_warnings = strip_escseq(warning.getvalue().replace(os.sep, '/'))
html_warnings_exp = HTML_WARNINGS % {
'root': re.escape(app.srcdir.replace(os.sep, '/'))}
assert re.match(html_warnings_exp + '$', html_warnings), \
@@ -404,11 +393,14 @@ def test_html_output(app, status, warning):
'--- Expected (regex):\n' + html_warnings_exp + \
'--- Got:\n' + html_warnings
+
+@gen_with_app(buildername='html', tags=['testtag'],
+ confoverrides={'html_context.hckey_co': 'hcval_co'})
+def test_html_output(app, status, warning):
+ app.builder.build_all()
for fname, paths in iteritems(HTML_XPATH):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for path, check in paths:
yield check_xpath, etree, fname, path, check
@@ -455,10 +447,8 @@ def test_tocdepth(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -497,10 +487,8 @@ def test_tocdepth_singlehtml(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -553,10 +541,8 @@ def test_numfig_disabled(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -596,7 +582,7 @@ def test_numfig_without_numbered_toctree(app, status, warning):
(".//li/a/span", '^Table:6$', True),
(".//li/a/span", '^Listing 9$', True),
(".//li/a/span", '^Code-6$', True),
- ],
+ ],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 1 $', True),
@@ -622,7 +608,7 @@ def test_numfig_without_numbered_toctree(app, status, warning):
"span[@class='caption-number']", '^Listing 3 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 4 $', True),
- ],
+ ],
'bar.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 5 $', True),
@@ -654,10 +640,8 @@ def test_numfig_without_numbered_toctree(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -693,7 +677,7 @@ def test_numfig_with_numbered_toctree(app, status, warning):
(".//li/a/span", '^Table:2.2$', True),
(".//li/a/span", '^Listing 1$', True),
(".//li/a/span", '^Code-2.2$', True),
- ],
+ ],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 1.1 $', True),
@@ -719,7 +703,7 @@ def test_numfig_with_numbered_toctree(app, status, warning):
"span[@class='caption-number']", '^Listing 1.3 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 1.4 $', True),
- ],
+ ],
'bar.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 2.1 $', True),
@@ -751,10 +735,8 @@ def test_numfig_with_numbered_toctree(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -793,7 +775,7 @@ def test_numfig_with_prefix(app, status, warning):
(".//li/a/span", '^Table:2.2$', True),
(".//li/a/span", '^Code-1$', True),
(".//li/a/span", '^Code-2.2$', True),
- ],
+ ],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Figure:1.1 $', True),
@@ -819,7 +801,7 @@ def test_numfig_with_prefix(app, status, warning):
"span[@class='caption-number']", '^Code-1.3 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Code-1.4 $', True),
- ],
+ ],
'bar.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Figure:2.1 $', True),
@@ -851,10 +833,8 @@ def test_numfig_with_prefix(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -890,7 +870,7 @@ def test_numfig_with_secnum_depth(app, status, warning):
(".//li/a/span", '^Table:2.1.2$', True),
(".//li/a/span", '^Listing 1$', True),
(".//li/a/span", '^Code-2.1.2$', True),
- ],
+ ],
'foo.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 1.1 $', True),
@@ -916,7 +896,7 @@ def test_numfig_with_secnum_depth(app, status, warning):
"span[@class='caption-number']", '^Listing 1.1.2 $', True),
(".//div[@class='code-block-caption']/"
"span[@class='caption-number']", '^Listing 1.2.1 $', True),
- ],
+ ],
'bar.html': [
(".//div[@class='figure']/p[@class='caption']/"
"span[@class='caption-number']", '^Fig. 2.1.1 $', True),
@@ -948,10 +928,8 @@ def test_numfig_with_secnum_depth(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@@ -980,34 +958,30 @@ def test_enumerable_node(app, status, warning):
}
for fname, paths in iteritems(expects):
- parser = NslessParser()
- parser.entity.update(html_entities.entitydefs)
with (app.outdir / fname).open('rb') as fp:
- etree = ET.parse(fp, parser)
+ etree = HTML_PARSER.parse(fp)
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
-@with_app(buildername='html')
-def test_jsmath(app, status, warning):
- app.builder.build_all()
- content = (app.outdir / 'math.html').text()
-
- assert '<div class="math">\na^2 + b^2 = c^2</div>' in content
- assert '<div class="math">\n\\begin{split}a + 1 &lt; b\\end{split}</div>' in content
- assert ('<span class="eqno">(1)</span><div class="math" id="equation-foo">\n'
- 'e^{i\\pi} = 1</div>' in content)
- assert ('<span class="eqno">(2)</span><div class="math">\n'
- 'e^{ix} = \\cos x + i\\sin x</div>' in content)
- assert '<div class="math">\nn \\in \\mathbb N</div>' in content
- assert '<div class="math">\na + 1 &lt; b</div>' in content
-
-
-@with_app(buildername='html', testroot='html_extra_path')
-def test_html_extra_path(app, status, warning):
+@with_app(buildername='html', testroot='html_assets')
+def test_html_assets(app, status, warning):
app.builder.build_all()
+ # html_static_path
+ assert not (app.outdir / '_static' / '.htaccess').exists()
+ assert not (app.outdir / '_static' / '.htpasswd').exists()
+ assert (app.outdir / '_static' / 'API.html').exists()
+ assert (app.outdir / '_static' / 'API.html').text() == 'Sphinx-1.4.4'
+ assert (app.outdir / '_static' / 'css/style.css').exists()
+ assert (app.outdir / '_static' / 'rimg.png').exists()
+ assert not (app.outdir / '_static' / '_build/index.html').exists()
+ assert (app.outdir / '_static' / 'background.png').exists()
+ assert not (app.outdir / '_static' / 'subdir' / '.htaccess').exists()
+ assert not (app.outdir / '_static' / 'subdir' / '.htpasswd').exists()
+
+ # html_extra_path
assert (app.outdir / '.htaccess').exists()
assert not (app.outdir / '.htpasswd').exists()
assert (app.outdir / 'API.html_t').exists()
@@ -1015,3 +989,17 @@ def test_html_extra_path(app, status, warning):
assert (app.outdir / 'rimg.png').exists()
assert not (app.outdir / '_build/index.html').exists()
assert (app.outdir / 'background.png').exists()
+ assert (app.outdir / 'subdir' / '.htaccess').exists()
+ assert not (app.outdir / 'subdir' / '.htpasswd').exists()
+
+
+@with_app(buildername='html', confoverrides={'html_sourcelink_suffix': ''})
+def test_html_sourcelink_suffix(app, status, warning):
+ app.builder.build_all()
+ content_otherext = (app.outdir / 'otherext.html').text()
+ content_images = (app.outdir / 'images.html').text()
+
+ assert '<a href="_sources/otherext.foo"' in content_otherext
+ assert '<a href="_sources/images.txt"' in content_images
+ assert (app.outdir / '_sources' / 'otherext.foo').exists()
+ assert (app.outdir / '_sources' / 'images.txt').exists()
diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py
index 264e2d2ef..54ba5811b 100644
--- a/tests/test_build_latex.py
+++ b/tests/test_build_latex.py
@@ -12,98 +12,87 @@ from __future__ import print_function
import os
import re
+from itertools import product
from subprocess import Popen, PIPE
from six import PY3
from sphinx.errors import SphinxError
+from sphinx.util.osutil import cd, ensuredir
from sphinx.writers.latex import LaTeXTranslator
-from util import SkipTest, remove_unicode_literals, with_app
+from util import SkipTest, remove_unicode_literals, with_app, strip_escseq
from test_build_html import ENV_WARNINGS
+LATEX_ENGINES = ['pdflatex', 'lualatex', 'xelatex']
+DOCCLASSES = ['howto', 'manual']
+STYLEFILES = ['article.sty', 'fancyhdr.sty', 'fancybox.sty', 'titlesec.sty', 'amsmath.sty',
+ 'framed.sty', 'color.sty', 'fancyvrb.sty', 'threeparttable.sty']
+
LATEX_WARNINGS = ENV_WARNINGS + """\
-%(root)s/markup.txt:164: WARNING: unknown option: &option
-%(root)s/footnote.txt:60: WARNING: citation not found: missing
-%(root)s/images.txt:20: WARNING: no matching candidate for image URI u'foo.\\*'
-%(root)s/markup.txt:285: WARNING: Could not lex literal_block as "c". Highlighting skipped.
+%(root)s/index.rst:\\d+: WARNING: unknown option: &option
+%(root)s/index.rst:\\d+: WARNING: citation not found: missing
+%(root)s/index.rst:\\d+: WARNING: no matching candidate for image URI u'foo.\\*'
+%(root)s/index.rst:\\d+: WARNING: Could not lex literal_block as "c". Highlighting skipped.
"""
if PY3:
LATEX_WARNINGS = remove_unicode_literals(LATEX_WARNINGS)
-def run_latex(outdir):
- """Run pdflatex, xelatex, and lualatex in the outdir"""
- cwd = os.getcwd()
- os.chdir(outdir)
+# only run latex if all needed packages are there
+def kpsetest(*filenames):
try:
- latexes = ('pdflatex', 'xelatex', 'lualatex')
- available_latexes = len(latexes)
- for latex in latexes:
- try:
- os.mkdir(latex)
- p = Popen([latex, '--interaction=nonstopmode',
- '-output-directory=%s' % latex, 'SphinxTests.tex'],
- stdout=PIPE, stderr=PIPE)
- except OSError: # most likely the latex executable was not found
- available_latexes -= 1
- else:
- stdout, stderr = p.communicate()
- if p.returncode != 0:
- print(stdout)
- print(stderr)
- assert False, '%s exited with return code %s' % (
- latex, p.returncode)
- finally:
- os.chdir(cwd)
-
- if available_latexes == 0: # no latex is available, skip the test
- raise SkipTest
-
-@with_app(buildername='latex', freshenv=True) # use freshenv to check warnings
-def test_latex(app, status, warning):
+ p = Popen(['kpsewhich'] + list(filenames), stdout=PIPE)
+ except OSError:
+ # no kpsewhich... either no tex distribution is installed or it is
+ # a "strange" one -- don't bother running latex
+ return None
+ else:
+ p.communicate()
+ if p.returncode != 0:
+ # not found
+ return False
+ # found
+ return True
+
+
+def test_latex():
+ if kpsetest(*STYLEFILES) is False:
+ raise SkipTest('not running latex, the required styles doesn\'t seem to be installed')
+
+ for engine, docclass in product(LATEX_ENGINES, DOCCLASSES):
+ yield build_latex_doc, engine, docclass
+
+
+@with_app(buildername='latex')
+def build_latex_doc(app, status, warning, engine, docclass):
+ app.config.latex_engine = engine
+ app.config.latex_documents[0] = app.config.latex_documents[0][:4] + (docclass,)
+
LaTeXTranslator.ignore_missing_images = True
app.builder.build_all()
- latex_warnings = warning.getvalue().replace(os.sep, '/')
- latex_warnings_exp = LATEX_WARNINGS % {
- 'root': re.escape(app.srcdir.replace(os.sep, '/'))}
- assert re.match(latex_warnings_exp + '$', latex_warnings), \
- 'Warnings don\'t match:\n' + \
- '--- Expected (regex):\n' + latex_warnings_exp + \
- '--- Got:\n' + latex_warnings
# file from latex_additional_files
assert (app.outdir / 'svgimg.svg').isfile()
- # only run latex if all needed packages are there
- def kpsetest(filename):
+ # now, try to run latex over it
+ with cd(app.outdir):
try:
- p = Popen(['kpsewhich', filename], stdout=PIPE)
- except OSError:
- # no kpsewhich... either no tex distribution is installed or it is
- # a "strange" one -- don't bother running latex
- return None
+ ensuredir(engine)
+ p = Popen([engine, '--interaction=nonstopmode',
+ '-output-directory=%s' % engine, 'SphinxTests.tex'],
+ stdout=PIPE, stderr=PIPE)
+ except OSError: # most likely the latex executable was not found
+ raise SkipTest
else:
- p.communicate()
+ stdout, stderr = p.communicate()
if p.returncode != 0:
- # not found
- return False
- # found
- return True
-
- if kpsetest('article.sty') is None:
- raise SkipTest('not running latex, it doesn\'t seem to be installed')
- for filename in ['fancyhdr.sty', 'fancybox.sty', 'titlesec.sty',
- 'amsmath.sty', 'framed.sty', 'color.sty', 'fancyvrb.sty',
- 'threeparttable.sty']:
- if not kpsetest(filename):
- raise SkipTest('not running latex, the %s package doesn\'t '
- 'seem to be installed' % filename)
-
- # now, try to run latex over it
- run_latex(app.outdir)
+ print(stdout)
+ print(stderr)
+ assert False, '%s exited with return code %s' % (
+ engine, p.returncode)
@with_app(buildername='latex')
@@ -111,62 +100,38 @@ def test_writer(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8')
+ assert ('\\begin{sphinxfigure-in-table}\n\\centering\n\\capstart\n'
+ '\\noindent\\sphinxincludegraphics{{img}.png}\n'
+ '\\sphinxfigcaption{figure in table}\\label{markup:id7}'
+ '\\end{sphinxfigure-in-table}\\relax' in result)
+
assert ('\\begin{wrapfigure}{r}{0pt}\n\\centering\n'
- '\\includegraphics{{rimg}.png}\n\\caption{figure with align option}'
- '\\label{markup:id7}\\end{wrapfigure}' in result)
+ '\\noindent\\sphinxincludegraphics{{rimg}.png}\n'
+ '\\caption{figure with align option}\\label{markup:id8}'
+ '\\end{wrapfigure}' in result)
assert ('\\begin{wrapfigure}{r}{0.500\\linewidth}\n\\centering\n'
- '\\includegraphics{{rimg}.png}\n\\caption{figure with align \\& figwidth option}'
- '\\label{markup:id8}\\end{wrapfigure}' in result)
+ '\\noindent\\sphinxincludegraphics{{rimg}.png}\n'
+ '\\caption{figure with align \\& figwidth option}\\label{markup:id9}'
+ '\\end{wrapfigure}' in result)
+ assert ('\\begin{wrapfigure}{r}{3cm}\n\\centering\n'
+ '\\noindent\\sphinxincludegraphics[width=3cm]{{rimg}.png}\n'
+ '\\caption{figure with align \\& width option}\\label{markup:id10}'
+ '\\end{wrapfigure}' in result)
-@with_app(buildername='latex', freshenv=True, # use freshenv to check warnings
- confoverrides={'latex_documents': [
- ('contents', 'SphinxTests.tex', 'Sphinx Tests Documentation',
- 'Georg Brandl \\and someone else', 'howto'),
- ]},
- srcdir='latex_howto')
-def test_latex_howto(app, status, warning):
- LaTeXTranslator.ignore_missing_images = True
+
+@with_app(buildername='latex', testroot='warnings', freshenv=True)
+def test_latex_warnings(app, status, warning):
app.builder.build_all()
- latex_warnings = warning.getvalue().replace(os.sep, '/')
- latex_warnings_exp = LATEX_WARNINGS % {
+
+ warnings = strip_escseq(warning.getvalue().replace(os.sep, '/'))
+ warnings_exp = LATEX_WARNINGS % {
'root': re.escape(app.srcdir.replace(os.sep, '/'))}
- assert re.match(latex_warnings_exp + '$', latex_warnings), \
+ assert re.match(warnings_exp + '$', warnings), \
'Warnings don\'t match:\n' + \
- '--- Expected (regex):\n' + latex_warnings_exp + \
- '--- Got:\n' + latex_warnings
-
- # file from latex_additional_files
- assert (app.outdir / 'svgimg.svg').isfile()
-
- # only run latex if all needed packages are there
- def kpsetest(filename):
- try:
- p = Popen(['kpsewhich', filename], stdout=PIPE)
- except OSError:
- # no kpsewhich... either no tex distribution is installed or it is
- # a "strange" one -- don't bother running latex
- return None
- else:
- p.communicate()
- if p.returncode != 0:
- # not found
- return False
- # found
- return True
-
- if kpsetest('article.sty') is None:
- raise SkipTest('not running latex, it doesn\'t seem to be installed')
- for filename in ['fancyhdr.sty', 'fancybox.sty', 'titlesec.sty',
- 'amsmath.sty', 'framed.sty', 'color.sty', 'fancyvrb.sty',
- 'threeparttable.sty']:
- if not kpsetest(filename):
- raise SkipTest('not running latex, the %s package doesn\'t '
- 'seem to be installed' % filename)
-
- # now, try to run latex over it
- run_latex(app.outdir)
+ '--- Expected (regex):\n' + warnings_exp + \
+ '--- Got:\n' + warnings
@with_app(buildername='latex', testroot='numfig',
@@ -179,7 +144,7 @@ def test_numref(app, status, warning):
print(warning.getvalue())
assert '\\addto\\captionsenglish{\\renewcommand{\\figurename}{Fig.\\@ }}' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\tablename}{Table }}' in result
- assert '\\SetupFloatingEnvironment{literal-block}{name=Listing }' in result
+ assert '\\addto\\captionsenglish{\\renewcommand{\\literalblockname}{Listing }}' in result
assert '\\hyperref[index:fig1]{Fig.\\@ \\ref{index:fig1}}' in result
assert '\\hyperref[baz:fig22]{Figure\\ref{baz:fig22}}' in result
assert '\\hyperref[index:table-1]{Table \\ref{index:table-1}}' in result
@@ -201,7 +166,7 @@ def test_numref_with_prefix1(app, status, warning):
print(warning.getvalue())
assert '\\addto\\captionsenglish{\\renewcommand{\\figurename}{Figure:}}' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\tablename}{Tab\\_}}' in result
- assert '\\SetupFloatingEnvironment{literal-block}{name=Code-}' in result
+ assert '\\addto\\captionsenglish{\\renewcommand{\\literalblockname}{Code-}}' in result
assert '\\ref{index:fig1}' in result
assert '\\ref{baz:fig22}' in result
assert '\\ref{index:table-1}' in result
@@ -231,7 +196,7 @@ def test_numref_with_prefix2(app, status, warning):
assert '\\def\\fnum@figure{\\figurename\\thefigure.\\@}' in result
assert '\\addto\\captionsenglish{\\renewcommand{\\tablename}{Tab\\_}}' in result
assert '\\def\\fnum@table{\\tablename\\thetable:}' in result
- assert '\\SetupFloatingEnvironment{literal-block}{name=Code-}' in result
+ assert '\\addto\\captionsenglish{\\renewcommand{\\literalblockname}{Code-}}' in result
assert '\\hyperref[index:fig1]{Figure:\\ref{index:fig1}.\\@}' in result
assert '\\hyperref[baz:fig22]{Figure\\ref{baz:fig22}}' in result
assert '\\hyperref[index:table-1]{Tab\\_\\ref{index:table-1}:}' in result
@@ -250,7 +215,7 @@ def test_numref_with_language_ja(app, status, warning):
print(warning.getvalue())
assert u'\\renewcommand{\\figurename}{\u56f3 }' in result
assert '\\renewcommand{\\tablename}{TABLE }' in result
- assert '\\SetupFloatingEnvironment{literal-block}{name=LIST }' in result
+ assert '\\renewcommand{\\literalblockname}{LIST }' in result
assert u'\\hyperref[index:fig1]{\u56f3 \\ref{index:fig1}}' in result
assert '\\hyperref[baz:fig22]{Figure\\ref{baz:fig22}}' in result
assert '\\hyperref[index:table-1]{TABLE \\ref{index:table-1}}' in result
@@ -396,18 +361,18 @@ def test_footnote(app, status, warning):
print(result)
print(status.getvalue())
print(warning.getvalue())
- assert '\\footnote[1]{\sphinxAtStartFootnote%\nnumbered\n}' in result
- assert '\\footnote[2]{\sphinxAtStartFootnote%\nauto numbered\n}' in result
- assert '\\footnote[3]{\sphinxAtStartFootnote%\nnamed\n}' in result
- assert '{\\hyperref[footnote:bar]{\\crossref{{[}bar{]}}}}' in result
+ assert '\\footnote[1]{\sphinxAtStartFootnote\nnumbered\n}' in result
+ assert '\\footnote[2]{\sphinxAtStartFootnote\nauto numbered\n}' in result
+ assert '\\footnote[3]{\sphinxAtStartFootnote\nnamed\n}' in result
+ assert '{\\hyperref[footnote:bar]{\\sphinxcrossref{{[}bar{]}}}}' in result
assert '\\bibitem[bar]{bar}{\\phantomsection\\label{footnote:bar} ' in result
assert '\\bibitem[bar]{bar}{\\phantomsection\\label{footnote:bar} \ncite' in result
assert '\\bibitem[bar]{bar}{\\phantomsection\\label{footnote:bar} \ncite\n}' in result
assert '\\capstart\\caption{Table caption \\protect\\footnotemark[4]}' in result
assert 'name \\protect\\footnotemark[5]' in result
assert ('\\end{threeparttable}\n\n'
- '\\footnotetext[4]{\sphinxAtStartFootnote%\nfootnotes in table caption\n}'
- '\\footnotetext[5]{\sphinxAtStartFootnote%\nfootnotes in table\n}' in result)
+ '\\footnotetext[4]{\sphinxAtStartFootnote\nfootnotes in table caption\n}'
+ '\\footnotetext[5]{\sphinxAtStartFootnote\nfootnotes in table\n}' in result)
@with_app(buildername='latex', testroot='footnotes')
@@ -418,23 +383,23 @@ def test_reference_in_caption(app, status, warning):
print(status.getvalue())
print(warning.getvalue())
assert ('\\caption{This is the figure caption with a reference to \\label{index:id2}'
- '{\\hyperref[index:authoryear]{\\crossref{{[}AuthorYear{]}}}}.}' in result)
+ '{\\hyperref[index:authoryear]{\\sphinxcrossref{{[}AuthorYear{]}}}}.}' in result)
assert '\\chapter{The section with a reference to {[}AuthorYear{]}}' in result
assert '\\caption{The table title with a reference to {[}AuthorYear{]}}' in result
assert '\\paragraph{The rubric title with a reference to {[}AuthorYear{]}}' in result
assert ('\\chapter{The section with a reference to \\protect\\footnotemark[4]}\n'
'\\label{index:the-section-with-a-reference-to}'
- '\\footnotetext[4]{\sphinxAtStartFootnote%\nFootnote in section\n}' in result)
+ '\\footnotetext[4]{\sphinxAtStartFootnote\nFootnote in section\n}' in result)
assert ('\\caption{This is the figure caption with a footnote to '
'\\protect\\footnotemark[6].}\label{index:id23}\end{figure}\n'
- '\\footnotetext[6]{\sphinxAtStartFootnote%\nFootnote in caption\n}')in result
+ '\\footnotetext[6]{\sphinxAtStartFootnote\nFootnote in caption\n}')in result
assert ('\\caption{footnote \\protect\\footnotemark[7] '
'in caption of normal table}') in result
- assert ('\\end{threeparttable}\n\n\\footnotetext[7]{\sphinxAtStartFootnote%\n'
+ assert ('\\end{threeparttable}\n\n\\footnotetext[7]{\sphinxAtStartFootnote\n'
'Foot note in table\n}' in result)
assert ('\\caption{footnote \\protect\\footnotemark[8] in caption of longtable}'
in result)
- assert ('\end{longtable}\n\n\\footnotetext[8]{\sphinxAtStartFootnote%\n'
+ assert ('\end{longtable}\n\n\\footnotetext[8]{\sphinxAtStartFootnote\n'
'Foot note in longtable\n}' in result)
@@ -446,27 +411,28 @@ def test_latex_show_urls_is_inline(app, status, warning):
print(result)
print(status.getvalue())
print(warning.getvalue())
- assert ('Same footnote number \\footnote[1]{\sphinxAtStartFootnote%\n'
+ assert ('Same footnote number \\footnote[1]{\sphinxAtStartFootnote\n'
'footnote in bar\n} in bar.rst' in result)
- assert ('Auto footnote number \\footnote[1]{\sphinxAtStartFootnote%\n'
+ assert ('Auto footnote number \\footnote[1]{\sphinxAtStartFootnote\n'
'footnote in baz\n} in baz.rst' in result)
assert ('\\phantomsection\\label{index:id26}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to\\string-authoryear]'
- '{\\crossref{The section with a reference to \\phantomsection\\label{index:id1}'
- '{\\hyperref[index:authoryear]{\\crossref{{[}AuthorYear{]}}}}}}}' in result)
+ '{\\sphinxcrossref{The section with a reference to '
+ '\\phantomsection\\label{index:id1}'
+ '{\\hyperref[index:authoryear]{\\sphinxcrossref{{[}AuthorYear{]}}}}}}}' in result)
assert ('\\phantomsection\\label{index:id27}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to]'
- '{\\crossref{The section with a reference to }}}' in result)
- assert 'First footnote: \\footnote[2]{\sphinxAtStartFootnote%\nFirst\n}' in result
- assert 'Second footnote: \\footnote[1]{\sphinxAtStartFootnote%\nSecond\n}' in result
+ '{\\sphinxcrossref{The section with a reference to }}}' in result)
+ assert 'First footnote: \\footnote[2]{\sphinxAtStartFootnote\nFirst\n}' in result
+ assert 'Second footnote: \\footnote[1]{\sphinxAtStartFootnote\nSecond\n}' in result
assert '\\href{http://sphinx-doc.org/}{Sphinx} (http://sphinx-doc.org/)' in result
- assert 'Third footnote: \\footnote[3]{\sphinxAtStartFootnote%\nThird\n}' in result
+ assert 'Third footnote: \\footnote[3]{\sphinxAtStartFootnote\nThird\n}' in result
assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde} '
'(http://sphinx-doc.org/\\textasciitilde{}test/)' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term} (http://sphinx-doc.org/)}] '
'\\leavevmode\nDescription' in result)
assert ('\\item[{Footnote in term \\protect\\footnotemark[5]}] '
- '\\leavevmode\\footnotetext[5]{\sphinxAtStartFootnote%\n'
+ '\\leavevmode\\footnotetext[5]{\sphinxAtStartFootnote\n'
'Footnote in term\n}\nDescription' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist} '
'(http://sphinx-doc.org/)}] \\leavevmode\nDescription' in result)
@@ -483,35 +449,36 @@ def test_latex_show_urls_is_footnote(app, status, warning):
print(result)
print(status.getvalue())
print(warning.getvalue())
- assert ('Same footnote number \\footnote[1]{\sphinxAtStartFootnote%\n'
+ assert ('Same footnote number \\footnote[1]{\sphinxAtStartFootnote\n'
'footnote in bar\n} in bar.rst' in result)
- assert ('Auto footnote number \\footnote[2]{\sphinxAtStartFootnote%\n'
+ assert ('Auto footnote number \\footnote[2]{\sphinxAtStartFootnote\n'
'footnote in baz\n} in baz.rst' in result)
assert ('\\phantomsection\\label{index:id26}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to\\string-authoryear]'
- '{\\crossref{The section with a reference to \\phantomsection\\label{index:id1}'
- '{\\hyperref[index:authoryear]{\\crossref{{[}AuthorYear{]}}}}}}}' in result)
+ '{\\sphinxcrossref{The section with a reference '
+ 'to \\phantomsection\\label{index:id1}'
+ '{\\hyperref[index:authoryear]{\\sphinxcrossref{{[}AuthorYear{]}}}}}}}' in result)
assert ('\\phantomsection\\label{index:id27}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to]'
- '{\\crossref{The section with a reference to }}}' in result)
- assert 'First footnote: \\footnote[3]{\sphinxAtStartFootnote%\nFirst\n}' in result
- assert 'Second footnote: \\footnote[1]{\sphinxAtStartFootnote%\nSecond\n}' in result
+ '{\\sphinxcrossref{The section with a reference to }}}' in result)
+ assert 'First footnote: \\footnote[3]{\sphinxAtStartFootnote\nFirst\n}' in result
+ assert 'Second footnote: \\footnote[1]{\sphinxAtStartFootnote\nSecond\n}' in result
assert ('\\href{http://sphinx-doc.org/}{Sphinx}'
- '\\footnote[4]{\sphinxAtStartFootnote%\n'
+ '\\footnote[4]{\sphinxAtStartFootnote\n'
'\\nolinkurl{http://sphinx-doc.org/}\n}' in result)
- assert 'Third footnote: \\footnote[6]{\sphinxAtStartFootnote%\nThird\n}' in result
+ assert 'Third footnote: \\footnote[6]{\sphinxAtStartFootnote\nThird\n}' in result
assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde}'
- '\\footnote[5]{\sphinxAtStartFootnote%\n'
+ '\\footnote[5]{\sphinxAtStartFootnote\n'
'\\nolinkurl{http://sphinx-doc.org/~test/}\n}' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}\\protect\\footnotemark[8]}] '
- '\\leavevmode\\footnotetext[8]{\sphinxAtStartFootnote%\n'
+ '\\leavevmode\\footnotetext[8]{\sphinxAtStartFootnote\n'
'\\nolinkurl{http://sphinx-doc.org/}\n}\nDescription' in result)
assert ('\\item[{Footnote in term \\protect\\footnotemark[10]}] '
- '\\leavevmode\\footnotetext[10]{\sphinxAtStartFootnote%\n'
+ '\\leavevmode\\footnotetext[10]{\sphinxAtStartFootnote\n'
'Footnote in term\n}\nDescription' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}\\protect'
'\\footnotemark[9]}] '
- '\\leavevmode\\footnotetext[9]{\sphinxAtStartFootnote%\n'
+ '\\leavevmode\\footnotetext[9]{\sphinxAtStartFootnote\n'
'\\nolinkurl{http://sphinx-doc.org/}\n}\nDescription' in result)
assert ('\\url{https://github.com/sphinx-doc/sphinx}\n' in result)
assert ('\\href{mailto:sphinx-dev@googlegroups.com}'
@@ -526,26 +493,27 @@ def test_latex_show_urls_is_no(app, status, warning):
print(result)
print(status.getvalue())
print(warning.getvalue())
- assert ('Same footnote number \\footnote[1]{\sphinxAtStartFootnote%\n'
+ assert ('Same footnote number \\footnote[1]{\sphinxAtStartFootnote\n'
'footnote in bar\n} in bar.rst' in result)
- assert ('Auto footnote number \\footnote[1]{\sphinxAtStartFootnote%\n'
+ assert ('Auto footnote number \\footnote[1]{\sphinxAtStartFootnote\n'
'footnote in baz\n} in baz.rst' in result)
assert ('\\phantomsection\\label{index:id26}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to\\string-authoryear]'
- '{\\crossref{The section with a reference to \\phantomsection\\label{index:id1}'
- '{\\hyperref[index:authoryear]{\\crossref{{[}AuthorYear{]}}}}}}}' in result)
+ '{\\sphinxcrossref{The section with a reference '
+ 'to \\phantomsection\\label{index:id1}'
+ '{\\hyperref[index:authoryear]{\\sphinxcrossref{{[}AuthorYear{]}}}}}}}' in result)
assert ('\\phantomsection\\label{index:id27}{\\hyperref[index:the\\string-section'
'\\string-with\\string-a\\string-reference\\string-to]'
- '{\\crossref{The section with a reference to }}}' in result)
- assert 'First footnote: \\footnote[2]{\sphinxAtStartFootnote%\nFirst\n}' in result
- assert 'Second footnote: \\footnote[1]{\sphinxAtStartFootnote%\nSecond\n}' in result
+ '{\\sphinxcrossref{The section with a reference to }}}' in result)
+ assert 'First footnote: \\footnote[2]{\sphinxAtStartFootnote\nFirst\n}' in result
+ assert 'Second footnote: \\footnote[1]{\sphinxAtStartFootnote\nSecond\n}' in result
assert '\\href{http://sphinx-doc.org/}{Sphinx}' in result
- assert 'Third footnote: \\footnote[3]{\sphinxAtStartFootnote%\nThird\n}' in result
+ assert 'Third footnote: \\footnote[3]{\sphinxAtStartFootnote\nThird\n}' in result
assert '\\href{http://sphinx-doc.org/~test/}{URL including tilde}' in result
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}}] '
'\\leavevmode\nDescription' in result)
assert ('\\item[{Footnote in term \\protect\\footnotemark[5]}] '
- '\\leavevmode\\footnotetext[5]{\sphinxAtStartFootnote%\n'
+ '\\leavevmode\\footnotetext[5]{\sphinxAtStartFootnote\n'
'Footnote in term\n}\nDescription' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}}] '
'\\leavevmode\nDescription' in result)
@@ -561,12 +529,13 @@ def test_image_in_section(app, status, warning):
print(result)
print(status.getvalue())
print(warning.getvalue())
- assert ('\chapter[Test section]'
- '{\includegraphics[width=15pt,height=15pt]{{pic}.png} Test section}'
+ assert ('\\chapter[Test section]{\\lowercase{\\sphinxincludegraphics'
+ '[width=15bp,height=15bp]}{{pic}.png} Test section}'
in result)
- assert ('\chapter[Other {[}blah{]} section]{Other {[}blah{]} '
- '\includegraphics[width=15pt,height=15pt]{{pic}.png} section}' in result)
- assert ('\chapter{Another section}' in result)
+ assert ('\\chapter[Other {[}blah{]} section]{Other {[}blah{]} '
+ '\\lowercase{\\sphinxincludegraphics[width=15bp,height=15bp]}'
+ '{{pic}.png} section}' in result)
+ assert ('\\chapter{Another section}' in result)
@with_app(buildername='latex', confoverrides={'latex_logo': 'notfound.jpg'})
diff --git a/tests/test_build_texinfo.py b/tests/test_build_texinfo.py
index 7f7570fd2..06da311df 100644
--- a/tests/test_build_texinfo.py
+++ b/tests/test_build_texinfo.py
@@ -18,32 +18,37 @@ from six import PY3
from sphinx.writers.texinfo import TexinfoTranslator
-from util import SkipTest, remove_unicode_literals, with_app
+from util import SkipTest, remove_unicode_literals, with_app, strip_escseq
from test_build_html import ENV_WARNINGS
TEXINFO_WARNINGS = ENV_WARNINGS + """\
-%(root)s/markup.txt:164: WARNING: unknown option: &option
-%(root)s/footnote.txt:60: WARNING: citation not found: missing
-%(root)s/images.txt:20: WARNING: no matching candidate for image URI u'foo.\\*'
-%(root)s/images.txt:29: WARNING: no matching candidate for image URI u'svgimg.\\*'
+%(root)s/index.rst:\\d+: WARNING: unknown option: &option
+%(root)s/index.rst:\\d+: WARNING: citation not found: missing
+%(root)s/index.rst:\\d+: WARNING: no matching candidate for image URI u'foo.\\*'
+%(root)s/index.rst:\\d+: WARNING: no matching candidate for image URI u'svgimg.\\*'
"""
if PY3:
TEXINFO_WARNINGS = remove_unicode_literals(TEXINFO_WARNINGS)
-@with_app('texinfo', freshenv=True) # use freshenv to check warnings
-def test_texinfo(app, status, warning):
- TexinfoTranslator.ignore_missing_images = True
+@with_app(buildername='texinfo', testroot='warnings', freshenv=True)
+def test_texinfo_warnings(app, status, warning):
app.builder.build_all()
- texinfo_warnings = warning.getvalue().replace(os.sep, '/')
- texinfo_warnings_exp = TEXINFO_WARNINGS % {
+ warnings = strip_escseq(warning.getvalue().replace(os.sep, '/'))
+ warnings_exp = TEXINFO_WARNINGS % {
'root': re.escape(app.srcdir.replace(os.sep, '/'))}
- assert re.match(texinfo_warnings_exp + '$', texinfo_warnings), \
+ assert re.match(warnings_exp + '$', warnings), \
'Warnings don\'t match:\n' + \
- '--- Expected (regex):\n' + texinfo_warnings_exp + \
- '--- Got:\n' + texinfo_warnings
+ '--- Expected (regex):\n' + warnings_exp + \
+ '--- Got:\n' + warnings
+
+
+@with_app(buildername='texinfo')
+def test_texinfo(app, status, warning):
+ TexinfoTranslator.ignore_missing_images = True
+ app.builder.build_all()
# now, try to run makeinfo over it
cwd = os.getcwd()
os.chdir(app.outdir)
diff --git a/tests/test_catalogs.py b/tests/test_catalogs.py
index ed9eb5fa3..ca6608490 100644
--- a/tests/test_catalogs.py
+++ b/tests/test_catalogs.py
@@ -56,6 +56,7 @@ def test_compile_all_catalogs(app, status, warning):
confoverrides={'language': 'en', 'locale_dirs': [locale_dir]})
def test_compile_specific_catalogs(app, status, warning):
catalog_dir = locale_dir / app.config.language / 'LC_MESSAGES'
+
def get_actual():
return set(find_files(catalog_dir, '.mo'))
diff --git a/tests/test_config.py b/tests/test_config.py
index d01d6afb4..b10711732 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -9,7 +9,7 @@
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
-from six import PY2, PY3, StringIO, iteritems
+from six import PY3, iteritems
from util import mock
from util import TestApp, with_app, gen_with_app, with_tempdir, \
@@ -109,8 +109,10 @@ def test_errors_warnings(dir):
u'# -*- coding: latin-1\nproject = "fooä"\n', encoding='latin-1')
cfg = Config(dir, 'conf.py', {}, None)
warned = [False]
+
def warn(msg):
warned[0] = True
+
cfg.check_unicode(warn)
assert warned[0]
@@ -160,18 +162,17 @@ def test_config_eol(tmpdir):
assert cfg.project == u'spam'
-@with_app(confoverrides={
- 'master_doc': 123,
- 'language': 'foo',
- 'primary_domain': None})
+@with_app(confoverrides={'master_doc': 123,
+ 'language': 'foo',
+ 'primary_domain': None})
def test_builtin_conf(app, status, warning):
warnings = warning.getvalue()
assert_in('master_doc', warnings,
- 'override on builtin "master_doc" should raise a type warning')
+ 'override on builtin "master_doc" should raise a type warning')
assert_not_in('language', warnings, 'explicitly permitted '
- 'override on builtin "language" should NOT raise a type warning')
+ 'override on builtin "language" should NOT raise a type warning')
assert_not_in('primary_domain', warnings, 'override to None on builtin '
- '"primary_domain" should NOT raise a type warning')
+ '"primary_domain" should NOT raise a type warning')
# See roots/test-config/conf.py.
@@ -193,12 +194,27 @@ TYPECHECK_WARNINGS = {
'value15': False,
'value16': False,
}
+
+
@gen_with_app(testroot='config')
def test_gen_check_types(app, status, warning):
if PY3:
TYPECHECK_WARNINGS['value11'] = False
for key, should in iteritems(TYPECHECK_WARNINGS):
- yield assert_in if should else assert_not_in, key, warning.getvalue(), \
- 'override on "%s" should%s raise a type warning' % \
- (key, '' if should else ' NOT')
+ yield assert_in if should else assert_not_in, key, warning.getvalue(), (
+ 'override on "%s" should%s raise a type warning' %
+ (key, '' if should else ' NOT')
+ )
+
+
+@with_app(testroot='config')
+def test_check_enum(app, status, warning):
+ assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
+ not in warning.getvalue()
+
+
+@with_app(testroot='config', confoverrides={'value17': 'invalid'})
+def test_check_enum_failed(app, status, warning):
+ assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
+ "but `invalid` is given." in warning.getvalue()
diff --git a/tests/test_correct_year.py b/tests/test_correct_year.py
index 7a156cbf2..2c2f0d812 100644
--- a/tests/test_correct_year.py
+++ b/tests/test_correct_year.py
@@ -16,10 +16,10 @@ from util import TestApp
def test_correct_year():
try:
# save current value of SOURCE_DATE_EPOCH
- sde = os.environ.pop('SOURCE_DATE_EPOCH',None)
+ sde = os.environ.pop('SOURCE_DATE_EPOCH', None)
# test with SOURCE_DATE_EPOCH unset: no modification
- app = TestApp(buildername='html',testroot='correct-year')
+ app = TestApp(buildername='html', testroot='correct-year')
app.builder.build_all()
content = (app.outdir / 'contents.html').text()
app.cleanup()
@@ -28,14 +28,14 @@ def test_correct_year():
# test with SOURCE_DATE_EPOCH set: copyright year should be
# updated
os.environ['SOURCE_DATE_EPOCH'] = "1293840000"
- app = TestApp(buildername='html',testroot='correct-year')
+ app = TestApp(buildername='html', testroot='correct-year')
app.builder.build_all()
content = (app.outdir / 'contents.html').text()
app.cleanup()
assert '2006-2011' in content
os.environ['SOURCE_DATE_EPOCH'] = "1293839999"
- app = TestApp(buildername='html',testroot='correct-year')
+ app = TestApp(buildername='html', testroot='correct-year')
app.builder.build_all()
content = (app.outdir / 'contents.html').text()
app.cleanup()
@@ -43,7 +43,7 @@ def test_correct_year():
finally:
# Restores SOURCE_DATE_EPOCH
- if sde == None:
- os.environ.pop('SOURCE_DATE_EPOCH',None)
+ if sde is None:
+ os.environ.pop('SOURCE_DATE_EPOCH', None)
else:
os.environ['SOURCE_DATE_EPOCH'] = sde
diff --git a/tests/test_directive_code.py b/tests/test_directive_code.py
index 84341a28c..175e1881e 100644
--- a/tests/test_directive_code.py
+++ b/tests/test_directive_code.py
@@ -65,8 +65,8 @@ def test_code_block_caption_html(app, status, warning):
def test_code_block_caption_latex(app, status, warning):
app.builder.build_all()
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
- caption = '\\SphinxSetupCaptionForVerbatim{literal-block}{caption \\emph{test} rb}'
- label = '\\def\\SphinxLiteralBlockLabel{\\label{caption:caption-test-rb}}'
+ caption = '\\sphinxSetupCaptionForVerbatim{caption \\sphinxstyleemphasis{test} rb}'
+ label = '\\def\\sphinxLiteralBlockLabel{\\label{caption:caption-test-rb}}'
link = '\hyperref[caption:caption-test-rb]' \
'{Listing \\ref{caption:caption-test-rb}}'
assert caption in latex
@@ -78,16 +78,16 @@ def test_code_block_caption_latex(app, status, warning):
def test_code_block_namedlink_latex(app, status, warning):
app.builder.build_all()
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
- label1 = '\def\SphinxLiteralBlockLabel{\label{caption:name-test-rb}}'
+ label1 = '\def\sphinxLiteralBlockLabel{\label{caption:name-test-rb}}'
link1 = '\\hyperref[caption:name\\string-test\\string-rb]'\
- '{\\crossref{\\DUrole{std,std-ref}{Ruby}}'
- label2 = '\def\SphinxLiteralBlockLabel{\label{namedblocks:some-ruby-code}}'
+ '{\\sphinxcrossref{\\DUrole{std,std-ref}{Ruby}}'
+ label2 = '\def\sphinxLiteralBlockLabel{\label{namedblocks:some-ruby-code}}'
link2 = '\\hyperref[namedblocks:some\\string-ruby\\string-code]'\
- '{\\crossref{\\DUrole{std,std-ref}{the ruby code}}}'
+ '{\\sphinxcrossref{\\DUrole{std,std-ref}{the ruby code}}}'
assert label1 in latex
- assert link1 in latex
+ assert link1 in latex
assert label2 in latex
- assert link2 in latex
+ assert link2 in latex
@with_app('xml', testroot='directive-code')
@@ -228,11 +228,12 @@ def test_literalinclude_file_whole_of_emptyline(app, status, warning):
app.builder.build_all()
latex = (app.outdir / 'Python.tex').text(encoding='utf-8').replace('\r\n', '\n')
includes = (
- '\\begin{Verbatim}[commandchars=\\\\\\{\\},numbers=left,firstnumber=1,stepnumber=1]\n'
+ '\\begin{sphinxVerbatim}'
+ '[commandchars=\\\\\\{\\},numbers=left,firstnumber=1,stepnumber=1]\n'
'\n'
'\n'
'\n'
- '\\end{Verbatim}\n')
+ '\\end{sphinxVerbatim}\n')
assert includes in latex
@@ -252,8 +253,8 @@ def test_literalinclude_caption_html(app, status, warning):
def test_literalinclude_caption_latex(app, status, warning):
app.builder.build('index')
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
- caption = '\\SphinxSetupCaptionForVerbatim{literal-block}{caption \\textbf{test} py}'
- label = '\\def\\SphinxLiteralBlockLabel{\\label{caption:caption-test-py}}'
+ caption = '\\sphinxSetupCaptionForVerbatim{caption \\sphinxstylestrong{test} py}'
+ label = '\\def\\sphinxLiteralBlockLabel{\\label{caption:caption-test-py}}'
link = '\hyperref[caption:caption-test-py]' \
'{Listing \\ref{caption:caption-test-py}}'
assert caption in latex
@@ -265,16 +266,16 @@ def test_literalinclude_caption_latex(app, status, warning):
def test_literalinclude_namedlink_latex(app, status, warning):
app.builder.build('index')
latex = (app.outdir / 'Python.tex').text(encoding='utf-8')
- label1 = '\def\SphinxLiteralBlockLabel{\label{caption:name-test-py}}'
+ label1 = '\def\sphinxLiteralBlockLabel{\label{caption:name-test-py}}'
link1 = '\\hyperref[caption:name\\string-test\\string-py]'\
- '{\\crossref{\\DUrole{std,std-ref}{Python}}'
- label2 = '\def\SphinxLiteralBlockLabel{\label{namedblocks:some-python-code}}'
+ '{\\sphinxcrossref{\\DUrole{std,std-ref}{Python}}'
+ label2 = '\def\sphinxLiteralBlockLabel{\label{namedblocks:some-python-code}}'
link2 = '\\hyperref[namedblocks:some\\string-python\\string-code]'\
- '{\\crossref{\\DUrole{std,std-ref}{the python code}}}'
+ '{\\sphinxcrossref{\\DUrole{std,std-ref}{the python code}}}'
assert label1 in latex
- assert link1 in latex
+ assert link1 in latex
assert label2 in latex
- assert link2 in latex
+ assert link2 in latex
@with_app('xml', testroot='directive-code')
diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py
index 4febe4239..b4e5ef073 100644
--- a/tests/test_domain_cpp.py
+++ b/tests/test_domain_cpp.py
@@ -24,7 +24,10 @@ ids = []
def parse(name, string):
- parser = DefinitionParser(string, None)
+ class Config(object):
+ cpp_id_attributes = ["id_attr"]
+ cpp_paren_attributes = ["paren_attr"]
+ parser = DefinitionParser(string, None, Config())
ast = parser.parse_declaration(name)
if not parser.eof:
print("Parsing stopped at", parser.pos)
@@ -77,7 +80,7 @@ def check(name, input, idv1output=None, idv2output=None, output=None):
print(rootSymbol.dump(0))
raise DefinitionError("")
ids.append(ast.get_id_v2())
- #print ".. %s:: %s" % (name, input)
+ # print ".. %s:: %s" % (name, input)
def test_fundamental_types():
@@ -132,6 +135,11 @@ def test_type_definitions():
check('type', 'A = B', None, '1A')
+ # from breathe#267 (named function parameters for function pointers
+ check('type', 'void (*gpio_callback_t)(struct device *port, uint32_t pin)',
+ 'gpio_callback_t', '15gpio_callback_t')
+ check('type', 'void (*f)(std::function<void(int i)> g)', 'f', '1f')
+
def test_concept_definitions():
check('concept', 'template<typename Param> A::B::Concept',
@@ -443,11 +451,43 @@ def test_templates():
None, 'IDpE8Numerics')
-#def test_print():
-# # used for getting all the ids out for checking
-# for a in ids:
-# print(a)
-# raise DefinitionError("")
+def test_attributes():
+ # style: C++
+ check('member', '[[]] int f', 'f__i', '1f')
+ check('member', '[ [ ] ] int f', 'f__i', '1f',
+ # this will fail when the proper grammar is implemented
+ output='[[ ]] int f')
+ check('member', '[[a]] int f', 'f__i', '1f')
+ # style: GNU
+ check('member', '__attribute__(()) int f', 'f__i', '1f')
+ check('member', '__attribute__((a)) int f', 'f__i', '1f')
+ check('member', '__attribute__((a, b)) int f', 'f__i', '1f')
+ # style: user-defined id
+ check('member', 'id_attr int f', 'f__i', '1f')
+ # style: user-defined paren
+ check('member', 'paren_attr() int f', 'f__i', '1f')
+ check('member', 'paren_attr(a) int f', 'f__i', '1f')
+ check('member', 'paren_attr("") int f', 'f__i', '1f')
+ check('member', 'paren_attr(()[{}][]{}) int f', 'f__i', '1f')
+ raises(DefinitionError, parse, 'member', 'paren_attr(() int f')
+ raises(DefinitionError, parse, 'member', 'paren_attr([) int f')
+ raises(DefinitionError, parse, 'member', 'paren_attr({) int f')
+ raises(DefinitionError, parse, 'member', 'paren_attr([)]) int f')
+ raises(DefinitionError, parse, 'member', 'paren_attr((])) int f')
+ raises(DefinitionError, parse, 'member', 'paren_attr({]}) int f')
+
+ # position: decl specs
+ check('function', 'static inline __attribute__(()) void f()',
+ 'f', '1fv',
+ output='__attribute__(()) static inline void f()')
+
+
+
+# def test_print():
+# # used for getting all the ids out for checking
+# for a in ids:
+# print(a)
+# raise DefinitionError("")
@with_app(testroot='domain-cpp', confoverrides={'add_function_parentheses': True})
diff --git a/tests/test_domain_rst.py b/tests/test_domain_rst.py
index c1f8c6caa..0d6dab5d8 100644
--- a/tests/test_domain_rst.py
+++ b/tests/test_domain_rst.py
@@ -11,8 +11,8 @@
from sphinx.domains.rst import parse_directive
-def test_parse_directive():
+def test_parse_directive():
s = parse_directive(u' foö ')
assert s == (u'foö', '')
diff --git a/tests/test_environment.py b/tests/test_environment.py
index b369d4609..f65a6f3f0 100644
--- a/tests/test_environment.py
+++ b/tests/test_environment.py
@@ -58,10 +58,6 @@ def test_images():
htmlbuilder = StandaloneHTMLBuilder(app)
htmlbuilder.imgpath = 'dummy'
htmlbuilder.post_process_images(tree)
- image_uri_message = "no matching candidate for image URI u'foo.*'"
- if PY3:
- image_uri_message = remove_unicode_literals(image_uri_message)
- assert image_uri_message in app._warning.content[-1]
assert set(htmlbuilder.images.keys()) == \
set(['subdir/img.png', 'img.png', 'subdir/simg.png', 'svgimg.svg',
'img.foo.png'])
@@ -71,7 +67,6 @@ def test_images():
app._warning.reset()
latexbuilder = LaTeXBuilder(app)
latexbuilder.post_process_images(tree)
- assert image_uri_message in app._warning.content[-1]
assert set(latexbuilder.images.keys()) == \
set(['subdir/img.png', 'subdir/simg.png', 'img.png', 'img.pdf',
'svgimg.pdf', 'img.foo.png'])
diff --git a/tests/test_ext_autosummary.py b/tests/test_ext_autosummary.py
index b2b04aea0..f8a8a3900 100644
--- a/tests/test_ext_autosummary.py
+++ b/tests/test_ext_autosummary.py
@@ -54,7 +54,7 @@ def test_mangle_signature():
assert res == outp, (u"'%s' -> '%s' != '%s'" % (inp, res, outp))
-@with_app(buildername='html', **default_kw)
+@with_app(buildername='dummy', **default_kw)
def test_get_items_summary(app, status, warning):
# monkey-patch Autosummary.get_items so we can easily get access to it's
# results..
diff --git a/tests/test_ext_githubpages.py b/tests/test_ext_githubpages.py
index 65276df7a..f74ed5315 100644
--- a/tests/test_ext_githubpages.py
+++ b/tests/test_ext_githubpages.py
@@ -9,8 +9,6 @@
:license: BSD, see LICENSE for details.
"""
-import re
-
from util import with_app
diff --git a/tests/test_ext_ifconfig.py b/tests/test_ext_ifconfig.py
index 56e31acae..835ab0938 100644
--- a/tests/test_ext_ifconfig.py
+++ b/tests/test_ext_ifconfig.py
@@ -9,11 +9,12 @@
:license: BSD, see LICENSE for details.
"""
-import re
-
from util import with_app
-@with_app(testroot='ext-ifconfig')
+@with_app(buildername='text', testroot='ext-ifconfig')
def test_ifconfig(app, status, warning):
app.builder.build_all()
+ result = (app.outdir / 'index.txt').text()
+ assert 'spam' in result
+ assert 'ham' not in result
diff --git a/tests/test_ext_intersphinx.py b/tests/test_ext_intersphinx.py
index 13b5d1aff..90987a3ef 100644
--- a/tests/test_ext_intersphinx.py
+++ b/tests/test_ext_intersphinx.py
@@ -43,6 +43,7 @@ module2 py:module 0 foo.html#module-$ -
module1.func py:function 1 sub/foo.html#$ -
CFunc c:function 2 cfunc.html#CFunc -
a term std:term -1 glossary.html#term-a-term -
+a term including:colon std:term -1 glossary.html#term-a-term-including-colon -
'''.encode('utf-8'))
@@ -78,6 +79,8 @@ def test_read_inventory_v2():
assert invdata1['c:function']['CFunc'][2] == '/util/cfunc.html#CFunc'
assert invdata1['std:term']['a term'][2] == \
'/util/glossary.html#term-a-term'
+ assert invdata1['std:term']['a term including:colon'][2] == \
+ '/util/glossary.html#term-a-term-including-colon'
@with_app()
diff --git a/tests/test_ext_math.py b/tests/test_ext_math.py
index 87219c294..af4b873d7 100644
--- a/tests/test_ext_math.py
+++ b/tests/test_ext_math.py
@@ -14,7 +14,24 @@ import re
from util import with_app, SkipTest
-@with_app('html', testroot='ext-math',
+@with_app(buildername='html', testroot='ext-math',
+ confoverrides = {'extensions': ['sphinx.ext.jsmath'], 'jsmath_path': 'dummy.js'})
+def test_jsmath(app, status, warning):
+ app.builder.build_all()
+ content = (app.outdir / 'math.html').text()
+
+ assert '<div class="math">\na^2 + b^2 = c^2</div>' in content
+ assert '<div class="math">\n\\begin{split}a + 1 &lt; b\\end{split}</div>' in content
+ assert (u'<span class="eqno">(1)<a class="headerlink" href="#equation-foo" '
+ u'title="Permalink to this equation">\xb6</a></span>'
+ u'<div class="math" id="equation-foo">\ne^{i\\pi} = 1</div>' in content)
+ assert ('<span class="eqno">(2)</span><div class="math">\n'
+ 'e^{ix} = \\cos x + i\\sin x</div>' in content)
+ assert '<div class="math">\nn \\in \\mathbb N</div>' in content
+ assert '<div class="math">\na + 1 &lt; b</div>' in content
+
+
+@with_app('html', testroot='ext-math-simple',
confoverrides = {'extensions': ['sphinx.ext.imgmath']})
def test_imgmath_png(app, status, warning):
app.builder.build_all()
@@ -28,7 +45,8 @@ def test_imgmath_png(app, status, warning):
'\s*alt="a\^2\+b\^2=c\^2"/>\s*</p>\s*</div>')
assert re.search(html, content, re.S)
-@with_app('html', testroot='ext-math',
+
+@with_app('html', testroot='ext-math-simple',
confoverrides={'extensions': ['sphinx.ext.imgmath'],
'imgmath_image_format': 'svg'})
def test_imgmath_svg(app, status, warning):
@@ -43,6 +61,7 @@ def test_imgmath_svg(app, status, warning):
'\s*alt="a\^2\+b\^2=c\^2"/>\s*</p>\s*</div>')
assert re.search(html, content, re.S)
+
@with_app('html', testroot='ext-math',
confoverrides={'extensions': ['sphinx.ext.mathjax']})
def test_mathjax_align(app, status, warning):
@@ -54,6 +73,7 @@ def test_mathjax_align(app, status, warning):
r'V \&amp;= \\frac\{4\}\{3\} \\pi r\^3\\end\{aligned\}\\end\{align\} \\\]</div>')
assert re.search(html, content, re.S)
+
@with_app('html', testroot='ext-math',
confoverrides={'math_number_all': True,
'extensions': ['sphinx.ext.mathjax']})
@@ -65,6 +85,7 @@ def test_math_number_all_mathjax(app, status, warning):
r'<span class="eqno">\(1\)</span>\\\[a\^2\+b\^2=c\^2\\\]</div>')
assert re.search(html, content, re.S)
+
@with_app('latex', testroot='ext-math',
confoverrides={'extensions': ['sphinx.ext.mathjax']})
def test_math_number_all_latex(app, status, warning):
diff --git a/tests/test_ext_napoleon_docstring.py b/tests/test_ext_napoleon_docstring.py
index ece55ebe4..c320a7fec 100644
--- a/tests/test_ext_napoleon_docstring.py
+++ b/tests/test_ext_napoleon_docstring.py
@@ -222,6 +222,24 @@ class GoogleDocstringTest(BaseDocstringTest):
"""
Single line summary
+ Args:
+ arg1 (list(int)): Description
+ arg2 (list[int]): Description
+ arg3 (dict(str, int)): Description
+ arg4 (dict[str, int]): Description
+ """,
+ """
+ Single line summary
+
+ :Parameters: * **arg1** (*list(int)*) -- Description
+ * **arg2** (*list[int]*) -- Description
+ * **arg3** (*dict(str, int)*) -- Description
+ * **arg4** (*dict[str, int]*) -- Description
+ """
+ ), (
+ """
+ Single line summary
+
Yield:
str:Extended
description of yielded value
@@ -329,7 +347,9 @@ Returns:
codecode
"""
expected = """
-:returns: foo::
+:returns:
+
+ foo::
codecode
codecode
diff --git a/tests/test_ext_todo.py b/tests/test_ext_todo.py
new file mode 100644
index 000000000..269a8a2be
--- /dev/null
+++ b/tests/test_ext_todo.py
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+"""
+ test_ext_todo
+ ~~~~~~~~~~~~~
+
+ Test sphinx.ext.todo extension.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import re
+from util import with_app
+
+
+@with_app('html', testroot='ext-todo', freshenv=True,
+ confoverrides={'todo_include_todos': True, 'todo_emit_warnings': True})
+def test_todo(app, status, warning):
+ todos = []
+
+ def on_todo_defined(app, node):
+ todos.append(node)
+
+ app.connect('todo-defined', on_todo_defined)
+ app.builder.build_all()
+
+ # check todolist
+ content = (app.outdir / 'index.html').text()
+ html = ('<p class="first admonition-title">Todo</p>\n'
+ '<p class="last">todo in foo</p>')
+ assert re.search(html, content, re.S)
+
+ html = ('<p class="first admonition-title">Todo</p>\n'
+ '<p class="last">todo in bar</p>')
+ assert re.search(html, content, re.S)
+
+ # check todo
+ content = (app.outdir / 'foo.html').text()
+ html = ('<p class="first admonition-title">Todo</p>\n'
+ '<p class="last">todo in foo</p>')
+ assert re.search(html, content, re.S)
+
+ # check emitted warnings
+ assert 'WARNING: TODO entry found: todo in foo' in warning.getvalue()
+ assert 'WARNING: TODO entry found: todo in bar' in warning.getvalue()
+
+ # check handled event
+ assert len(todos) == 2
+ assert set(todo[1].astext() for todo in todos) == set(['todo in foo', 'todo in bar'])
+
+
+@with_app('html', testroot='ext-todo', freshenv=True,
+ confoverrides={'todo_include_todos': False, 'todo_emit_warnings': True})
+def test_todo_not_included(app, status, warning):
+ todos = []
+
+ def on_todo_defined(app, node):
+ todos.append(node)
+
+ app.connect('todo-defined', on_todo_defined)
+ app.builder.build_all()
+
+ # check todolist
+ content = (app.outdir / 'index.html').text()
+ html = ('<p class="first admonition-title">Todo</p>\n'
+ '<p class="last">todo in foo</p>')
+ assert not re.search(html, content, re.S)
+
+ html = ('<p class="first admonition-title">Todo</p>\n'
+ '<p class="last">todo in bar</p>')
+ assert not re.search(html, content, re.S)
+
+ # check todo
+ content = (app.outdir / 'foo.html').text()
+ html = ('<p class="first admonition-title">Todo</p>\n'
+ '<p class="last">todo in foo</p>')
+ assert not re.search(html, content, re.S)
+
+ # check emitted warnings
+ assert 'WARNING: TODO entry found: todo in foo' in warning.getvalue()
+ assert 'WARNING: TODO entry found: todo in bar' in warning.getvalue()
+
+ # check handled event
+ assert len(todos) == 2
+ assert set(todo[1].astext() for todo in todos) == set(['todo in foo', 'todo in bar'])
diff --git a/tests/test_highlighting.py b/tests/test_highlighting.py
index 176565f62..328abdf31 100644
--- a/tests/test_highlighting.py
+++ b/tests/test_highlighting.py
@@ -65,7 +65,7 @@ def test_detect_interactive():
def test_lexer_options():
bridge = PygmentsBridge('html')
- ret = bridge.highlight_block('//comment', 'php', opts={'startinline' : True})
+ ret = bridge.highlight_block('//comment', 'php', opts={'startinline': True})
assert '<span class="c1">//comment</span>' in ret
diff --git a/tests/test_i18n.py b/tests/test_i18n.py
deleted file mode 100644
index fcb35fc42..000000000
--- a/tests/test_i18n.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- test_i18n
- ~~~~~~~~~
-
- Test locale features.
-
- :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
- :license: BSD, see LICENSE for details.
-"""
-
-from util import with_app
-
-
-@with_app(confoverrides={'language': 'de'})
-def test_i18n(app, status, warning):
- app.builder.build_all()
diff --git a/tests/test_intl.py b/tests/test_intl.py
index 47a51589d..b31f1678b 100644
--- a/tests/test_intl.py
+++ b/tests/test_intl.py
@@ -680,7 +680,7 @@ def test_xml_builder(app, status, warning):
def test_additional_targets_should_not_be_translated(app, status, warning):
app.builder.build_all()
- ## literalblock.txt
+ # [literalblock.txt]
result = (app.outdir / 'literalblock.html').text(encoding='utf-8')
# title should be translated
@@ -707,7 +707,7 @@ def test_additional_targets_should_not_be_translated(app, status, warning):
"""<span class="c1"># sys importing</span>""")
yield assert_count(expected_expr, result, 1)
- ## raw.txt
+ # [raw.txt]
result = (app.outdir / 'raw.html').text(encoding='utf-8')
@@ -715,7 +715,7 @@ def test_additional_targets_should_not_be_translated(app, status, warning):
expected_expr = """<iframe src="http://sphinx-doc.org"></iframe></div>"""
yield assert_count(expected_expr, result, 1)
- ## figure.txt
+ # [figure.txt]
result = (app.outdir / 'figure.html').text(encoding='utf-8')
@@ -741,7 +741,7 @@ def test_additional_targets_should_not_be_translated(app, status, warning):
def test_additional_targets_should_be_translated(app, status, warning):
app.builder.build_all()
- ## literalblock.txt
+ # [literalblock.txt]
result = (app.outdir / 'literalblock.html').text(encoding='utf-8')
# title should be translated
@@ -768,7 +768,7 @@ def test_additional_targets_should_be_translated(app, status, warning):
"""<span class="c1"># SYS IMPORTING</span>""")
yield assert_count(expected_expr, result, 1)
- ## raw.txt
+ # [raw.txt]
result = (app.outdir / 'raw.html').text(encoding='utf-8')
@@ -776,7 +776,7 @@ def test_additional_targets_should_be_translated(app, status, warning):
expected_expr = """<iframe src="HTTP://SPHINX-DOC.ORG"></iframe></div>"""
yield assert_count(expected_expr, result, 1)
- ## figure.txt
+ # [figure.txt]
result = (app.outdir / 'figure.html').text(encoding='utf-8')
diff --git a/tests/test_markup.py b/tests/test_markup.py
index d12138692..102235e1d 100644
--- a/tests/test_markup.py
+++ b/tests/test_markup.py
@@ -41,6 +41,7 @@ def setup_module():
def teardown_module():
app.cleanup()
+
# since we're not resolving the markup afterwards, these nodes may remain
class ForgivingTranslator:
def visit_pending_xref(self, node):
@@ -74,11 +75,12 @@ def verify_re(rst, html_expected, latex_expected):
if latex_expected:
latex_translator = ForgivingLaTeXTranslator(document, app.builder)
- latex_translator.first_document = -1 # don't write \begin{document}
+ latex_translator.first_document = -1 # don't write \begin{document}
document.walkabout(latex_translator)
latex_translated = ''.join(latex_translator.body).strip()
assert re.match(latex_expected, latex_translated), 'from ' + repr(rst)
+
def verify(rst, html_expected, latex_expected):
if html_expected:
html_expected = re.escape(html_expected) + '$'
@@ -91,32 +93,32 @@ def test_inline():
# correct interpretation of code with whitespace
_html = ('<p><code class="(samp )?docutils literal"><span class="pre">'
'code</span>&nbsp;&nbsp; <span class="pre">sample</span></code></p>')
- yield verify_re, '``code sample``', _html, r'\\code{code sample}'
- yield verify_re, ':samp:`code sample`', _html, r'\\code{code sample}'
+ yield verify_re, '``code sample``', _html, r'\\sphinxcode{code sample}'
+ yield verify_re, ':samp:`code sample`', _html, r'\\sphinxcode{code sample}'
# interpolation of braces in samp and file roles (HTML only)
yield (verify, ':samp:`a{b}c`',
'<p><code class="samp docutils literal"><span class="pre">a</span>'
'<em><span class="pre">b</span></em>'
'<span class="pre">c</span></code></p>',
- '\\code{a\\emph{b}c}')
+ '\\sphinxcode{a\\sphinxstyleemphasis{b}c}')
# interpolation of arrows in menuselection
yield (verify, ':menuselection:`a --> b`',
u'<p><span class="menuselection">a \N{TRIANGULAR BULLET} b</span></p>',
- '\\menuselection{a \\(\\rightarrow\\) b}')
+ '\\sphinxmenuselection{a \\(\\rightarrow\\) b}')
# interpolation of ampersands in guilabel/menuselection
yield (verify, ':guilabel:`&Foo -&&- &Bar`',
u'<p><span class="guilabel"><span class="accelerator">F</span>oo '
'-&amp;- <span class="accelerator">B</span>ar</span></p>',
- r'\menuselection{\accelerator{F}oo -\&- \accelerator{B}ar}')
+ r'\sphinxmenuselection{\sphinxaccelerator{F}oo -\&- \sphinxaccelerator{B}ar}')
# non-interpolation of dashes in option role
yield (verify_re, ':option:`--with-option`',
'<p><code( class="xref std std-option docutils literal")?>'
'<span class="pre">--with-option</span></code></p>$',
- r'\\code{-{-}with-option}$')
+ r'\\sphinxcode{-{-}with-option}$')
# verify smarty-pants quotes
yield verify, '"John"', '<p>&#8220;John&#8221;</p>', "``John''"
@@ -124,12 +126,13 @@ def test_inline():
yield (verify, '``"John"``',
'<p><code class="docutils literal"><span class="pre">'
'&quot;John&quot;</span></code></p>',
- '\\code{"John"}')
+ '\\sphinxcode{"John"}')
# verify classes for inline roles
yield (verify, ':manpage:`mp(1)`',
'<p><em class="manpage">mp(1)</em></p>',
- '\\emph{\\texttt{mp(1)}}')
+ '\\sphinxstyleliteralemphasis{mp(1)}')
+
def test_latex_escaping():
# correct escaping in normal mode
@@ -137,9 +140,9 @@ def test_latex_escaping():
r'\(\Gamma\)\textbackslash{}\(\infty\)\$')
# in verbatim code fragments
yield (verify, u'::\n\n @Γ\\∞${}', None,
- u'\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n'
+ u'\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]\n'
u'@\\(\\Gamma\\)\\PYGZbs{}\\(\\infty\\)\\PYGZdl{}\\PYGZob{}\\PYGZcb{}\n'
- u'\\end{Verbatim}')
+ u'\\end{sphinxVerbatim}')
# in URIs
yield (verify_re, u'`test <http://example.com/~me/>`_', None,
r'\\href{http://example.com/~me/}{test}.*')
diff --git a/tests/test_search.py b/tests/test_search.py
index 212ce778c..63d78df46 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -21,6 +21,7 @@ from util import with_app
settings = parser = None
+
def setup_module():
global settings, parser
optparser = frontend.OptionParser(components=(rst.Parser,))
@@ -45,13 +46,14 @@ FILE_CONTENTS = '''\
test that non-comments are indexed: fermion
'''
+
def test_wordcollector():
doc = utils.new_document(b'test data', settings)
doc['file'] = 'dummy'
parser.parse(FILE_CONTENTS, doc)
ix = IndexBuilder(None, 'en', {}, None)
- ix.feed('filename', 'title', doc)
+ ix.feed('docname', 'filename', 'title', doc)
assert 'boson' not in ix._mapping
assert 'fermion' in ix._mapping
@@ -90,3 +92,16 @@ def test_meta_keys_are_handled_for_language_de(app, status, warning):
assert is_registered_term(searchindex, 'onlygerman')
assert not is_registered_term(searchindex, 'notgerman')
assert is_registered_term(searchindex, 'onlytoogerman')
+
+
+@with_app(testroot='search')
+def test_stemmer_does_not_remove_short_words(app, status, warning):
+ app.builder.build_all()
+ searchindex = (app.outdir / 'searchindex.js').text()
+ assert 'zfs' in searchindex
+
+
+@with_app(testroot='search')
+def test_stemmer(app, status, warning):
+ searchindex = (app.outdir / 'searchindex.js').text()
+ assert 'findthisstemmedkei' in searchindex
diff --git a/tests/test_searchadapters.py b/tests/test_searchadapters.py
index f6a389fea..ee350182f 100644
--- a/tests/test_searchadapters.py
+++ b/tests/test_searchadapters.py
@@ -22,7 +22,7 @@ def teardown_module():
def search_adapter_helper(adapter):
- settings = {'srcdir': rootdir / 'root',
+ settings = {'srcdir': rootdir / 'roots' / 'test-searchadapters',
'builddir': tempdir / 'websupport',
'status': StringIO(),
'warning': StringIO(),
@@ -41,7 +41,7 @@ def search_adapter_helper(adapter):
# Make sure documents are properly updated by the search adapter.
s.init_indexing(changed=['markup'])
- s.add_document(u'markup', u'title', u'SomeLongRandomWord')
+ s.add_document(u'markup', u'filename', u'title', u'SomeLongRandomWord')
s.finish_indexing()
# Now a search for "Epigraph" should return zero results.
results = s.query(u'Epigraph')
diff --git a/tests/test_setup_command.py b/tests/test_setup_command.py
index 77c9ade46..c92f6220f 100644
--- a/tests/test_setup_command.py
+++ b/tests/test_setup_command.py
@@ -108,3 +108,25 @@ def test_build_sphinx_return_nonzero_status(pkgroot, proc):
print(out)
print(err)
assert proc.returncode != 0, 'expect non-zero status for setup.py'
+
+
+@with_setup_command(root)
+def test_build_sphinx_warning_return_zero_status(pkgroot, proc):
+ srcdir = (pkgroot / 'doc')
+ (srcdir / 'contents.txt').write_text(
+ 'See :ref:`unexisting-reference-label`')
+ out, err = proc.communicate()
+ print(out)
+ print(err)
+ assert proc.returncode == 0
+
+
+@with_setup_command(root, '--warning-is-error')
+def test_build_sphinx_warning_is_error_return_nonzero_status(pkgroot, proc):
+ srcdir = (pkgroot / 'doc')
+ (srcdir / 'contents.txt').write_text(
+ 'See :ref:`unexisting-reference-label`')
+ out, err = proc.communicate()
+ print(out)
+ print(err)
+ assert proc.returncode != 0, 'expect non-zero status for setup.py'
diff --git a/tests/test_theming.py b/tests/test_theming.py
index 07787ecca..d4c104c8c 100644
--- a/tests/test_theming.py
+++ b/tests/test_theming.py
@@ -26,7 +26,7 @@ def test_theme_api(app, status, warning):
assert set(Theme.themes.keys()) == \
set(['basic', 'default', 'scrolls', 'agogo', 'sphinxdoc', 'haiku',
'traditional', 'testtheme', 'ziptheme', 'epub', 'nature',
- 'pyramid', 'bizstyle', 'classic'])
+ 'pyramid', 'bizstyle', 'classic', 'nonav'])
assert Theme.themes['testtheme'][1] is None
assert isinstance(Theme.themes['ziptheme'][1], zipfile.ZipFile)
@@ -66,7 +66,7 @@ def test_js_source(app, status, warning):
app.builder.build(['contents'])
- v = '1.11.1'
+ v = '3.1.0'
msg = 'jquery.js version does not match to {v}'.format(v=v)
jquery_min = (app.outdir / '_static' / 'jquery.js').text()
assert 'jQuery v{v}'.format(v=v) in jquery_min, msg
diff --git a/tests/test_util_fileutil.py b/tests/test_util_fileutil.py
new file mode 100644
index 000000000..a56543614
--- /dev/null
+++ b/tests/test_util_fileutil.py
@@ -0,0 +1,114 @@
+# -*- coding: utf-8 -*-
+"""
+ test_util_fileutil
+ ~~~~~~~~~~~~~~~~~~
+
+ Tests sphinx.util.fileutil functions.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from sphinx.util.fileutil import copy_asset, copy_asset_file
+from sphinx.jinja2glue import BuiltinTemplateLoader
+
+from mock import Mock
+from util import with_tempdir
+
+
+class DummyTemplateLoader(BuiltinTemplateLoader):
+ def __init__(self):
+ BuiltinTemplateLoader.__init__(self)
+ builder = Mock()
+ builder.config.templates_path = []
+ builder.app.translater = None
+ self.init(builder)
+
+
+@with_tempdir
+def test_copy_asset_file(tmpdir):
+ renderer = DummyTemplateLoader()
+
+ # copy normal file
+ src = (tmpdir / 'asset.txt')
+ src.write_text('# test data')
+ dest = (tmpdir / 'output.txt')
+
+ copy_asset_file(src, dest)
+ assert dest.exists()
+ assert src.text() == dest.text()
+
+ # copy template file
+ src = (tmpdir / 'asset.txt_t')
+ src.write_text('# {{var1}} data')
+ dest = (tmpdir / 'output.txt_t')
+
+ copy_asset_file(src, dest, {'var1': 'template'}, renderer)
+ assert not dest.exists()
+ assert (tmpdir / 'output.txt').exists()
+ assert (tmpdir / 'output.txt').text() == '# template data'
+
+ # copy template file to subdir
+ src = (tmpdir / 'asset.txt_t')
+ src.write_text('# {{var1}} data')
+ subdir1 = (tmpdir / 'subdir')
+ subdir1.makedirs()
+
+ copy_asset_file(src, subdir1, {'var1': 'template'}, renderer)
+ assert (subdir1 / 'asset.txt').exists()
+ assert (subdir1 / 'asset.txt').text() == '# template data'
+
+ # copy template file without context
+ src = (tmpdir / 'asset.txt_t')
+ subdir2 = (tmpdir / 'subdir2')
+ subdir2.makedirs()
+
+ copy_asset_file(src, subdir2)
+ assert not (subdir2 / 'asset.txt').exists()
+ assert (subdir2 / 'asset.txt_t').exists()
+ assert (subdir2 / 'asset.txt_t').text() == '# {{var1}} data'
+
+
+@with_tempdir
+def test_copy_asset(tmpdir):
+ renderer = DummyTemplateLoader()
+
+ # prepare source files
+ source = (tmpdir / 'source')
+ source.makedirs()
+ (source / 'index.rst').write_text('index.rst')
+ (source / 'foo.rst_t').write_text('{{var1}}.rst')
+ (source / '_static').makedirs()
+ (source / '_static' / 'basic.css').write_text('basic.css')
+ (source / '_templates').makedirs()
+ (source / '_templates' / 'layout.html').write_text('layout.html')
+ (source / '_templates' / 'sidebar.html_t').write_text('sidebar: {{var2}}')
+
+ # copy a single file
+ assert not (tmpdir / 'test1').exists()
+ copy_asset(source / 'index.rst', tmpdir / 'test1')
+ assert (tmpdir / 'test1').exists()
+ assert (tmpdir / 'test1/index.rst').exists()
+
+ # copy directories
+ destdir = tmpdir / 'test2'
+ copy_asset(source, destdir, context=dict(var1='bar', var2='baz'), renderer=renderer)
+ assert (destdir / 'index.rst').exists()
+ assert (destdir / 'foo.rst').exists()
+ assert (destdir / 'foo.rst').text() == 'bar.rst'
+ assert (destdir / '_static' / 'basic.css').exists()
+ assert (destdir / '_templates' / 'layout.html').exists()
+ assert (destdir / '_templates' / 'sidebar.html').exists()
+ assert (destdir / '_templates' / 'sidebar.html').text() == 'sidebar: baz'
+
+ # copy with exclusion
+ def excluded(path):
+ return ('sidebar.html' in path or 'basic.css' in path)
+
+ destdir = tmpdir / 'test3'
+ copy_asset(source, destdir, excluded,
+ context=dict(var1='bar', var2='baz'), renderer=renderer)
+ assert (destdir / 'index.rst').exists()
+ assert (destdir / 'foo.rst').exists()
+ assert not (destdir / '_static' / 'basic.css').exists()
+ assert (destdir / '_templates' / 'layout.html').exists()
+ assert not (destdir / '_templates' / 'sidebar.html').exists()
diff --git a/tests/test_util_i18n.py b/tests/test_util_i18n.py
index 6ff988c81..3e0cfd5f3 100644
--- a/tests/test_util_i18n.py
+++ b/tests/test_util_i18n.py
@@ -47,7 +47,7 @@ def test_catalog_outdated(dir):
mo_file.write_text('#')
assert not cat.is_outdated() # if mo is exist and newer than po
- os.utime(mo_file, (os.stat(mo_file).st_mtime - 10,) * 2) # to be outdate
+ os.utime(mo_file, (os.stat(mo_file).st_mtime - 10,) * 2) # to be outdate
assert cat.is_outdated() # if mo is exist and older than po
@@ -213,6 +213,7 @@ def test_format_date():
assert i18n.format_date(format, date=datet) == 'Feb 7, 2016, 5:11:17 AM'
assert i18n.format_date(format, date=date) == 'Feb 7, 2016'
+
def test_get_filename_for_language():
app = TestApp()
diff --git a/tests/test_util_inspect.py b/tests/test_util_inspect.py
new file mode 100644
index 000000000..2dcbc37d5
--- /dev/null
+++ b/tests/test_util_inspect.py
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+"""
+ test_util_inspect
+ ~~~~~~~~~~~~~~~
+
+ Tests util.inspect functions.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from unittest import TestCase
+
+from sphinx.util import inspect
+
+
+class TestSafeGetAttr(TestCase):
+ def test_safe_getattr_with_default(self):
+ class Foo(object):
+ def __getattr__(self, item):
+ raise Exception
+
+ obj = Foo()
+
+ result = inspect.safe_getattr(obj, 'bar', 'baz')
+
+ assert result == 'baz'
+
+ def test_safe_getattr_with_exception(self):
+ class Foo(object):
+ def __getattr__(self, item):
+ raise Exception
+
+ obj = Foo()
+
+ try:
+ inspect.safe_getattr(obj, 'bar')
+ except AttributeError as exc:
+ self.assertEqual(exc.args[0], 'bar')
+ else:
+ self.fail('AttributeError not raised')
+
+ def test_safe_getattr_with_property_exception(self):
+ class Foo(object):
+ @property
+ def bar(self):
+ raise Exception
+
+ obj = Foo()
+
+ try:
+ inspect.safe_getattr(obj, 'bar')
+ except AttributeError as exc:
+ self.assertEqual(exc.args[0], 'bar')
+ else:
+ self.fail('AttributeError not raised')
+
+ def test_safe_getattr_with___dict___override(self):
+ class Foo(object):
+ @property
+ def __dict__(self):
+ raise Exception
+
+ obj = Foo()
+
+ try:
+ inspect.safe_getattr(obj, 'bar')
+ except AttributeError as exc:
+ self.assertEqual(exc.args[0], 'bar')
+ else:
+ self.fail('AttributeError not raised')
diff --git a/tests/test_util_jsdump.py b/tests/test_util_jsdump.py
new file mode 100644
index 000000000..f8d31568d
--- /dev/null
+++ b/tests/test_util_jsdump.py
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+
+def test_jsdump():
+ from sphinx.util.jsdump import dumps
+
+ assert dumps({'1a': 1}) == '{"1a":1}'
+ assert dumps({'a1': 1}) == '{a1:1}'
+
+ assert dumps({u'a\xe8': 1}) == '{"a\\u00e8":1}'
diff --git a/tests/test_util_matching.py b/tests/test_util_matching.py
new file mode 100644
index 000000000..9e99a5322
--- /dev/null
+++ b/tests/test_util_matching.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+"""
+ test_util_matching
+ ~~~~~~~~~~~~~~~~~~
+
+ Tests sphinx.util.matching functions.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from sphinx.util.matching import compile_matchers, Matcher
+
+
+def test_compile_matchers():
+ # exact matching
+ pat = compile_matchers(['hello.py']).pop()
+ assert pat('hello.py')
+ assert not pat('hello-py')
+ assert not pat('subdir/hello.py')
+
+ # wild card (*)
+ pat = compile_matchers(['hello.*']).pop()
+ assert pat('hello.py')
+ assert pat('hello.rst')
+
+ pat = compile_matchers(['*.py']).pop()
+ assert pat('hello.py')
+ assert pat('world.py')
+ assert not pat('subdir/hello.py')
+
+ # wild card (**)
+ pat = compile_matchers(['hello.**']).pop()
+ assert pat('hello.py')
+ assert pat('hello.rst')
+ assert pat('hello.py/world.py')
+
+ pat = compile_matchers(['**.py']).pop()
+ assert pat('hello.py')
+ assert pat('world.py')
+ assert pat('subdir/hello.py')
+
+ pat = compile_matchers(['**/hello.py']).pop()
+ assert not pat('hello.py')
+ assert pat('subdir/hello.py')
+ assert pat('subdir/subdir/hello.py')
+
+ # wild card (?)
+ pat = compile_matchers(['hello.?']).pop()
+ assert pat('hello.c')
+ assert not pat('hello.py')
+
+ # pattern ([...])
+ pat = compile_matchers(['hello[12\\].py']).pop()
+ assert pat('hello1.py')
+ assert pat('hello2.py')
+ assert pat('hello\\.py')
+ assert not pat('hello3.py')
+
+ pat = compile_matchers(['hello[^12].py']).pop() # "^" is not negative identifier
+ assert pat('hello1.py')
+ assert pat('hello2.py')
+ assert pat('hello^.py')
+ assert not pat('hello3.py')
+
+ # negative pattern ([!...])
+ pat = compile_matchers(['hello[!12].py']).pop()
+ assert not pat('hello1.py')
+ assert not pat('hello2.py')
+ assert not pat('hello/.py') # negative pattern does not match to "/"
+ assert pat('hello3.py')
+
+ # non patterns
+ pat = compile_matchers(['hello[.py']).pop()
+ assert pat('hello[.py')
+ assert not pat('hello.py')
+
+ pat = compile_matchers(['hello[].py']).pop()
+ assert pat('hello[].py')
+ assert not pat('hello.py')
+
+ pat = compile_matchers(['hello[!].py']).pop()
+ assert pat('hello[!].py')
+ assert not pat('hello.py')
+
+
+def test_Matcher():
+ matcher = Matcher(['hello.py', '**/world.py'])
+ assert matcher('hello.py')
+ assert not matcher('subdir/hello.py')
+ assert matcher('world.py')
+ assert matcher('subdir/world.py')
diff --git a/tests/test_util_nodes.py b/tests/test_util_nodes.py
index a41af3cc8..e7a4b7e90 100644
--- a/tests/test_util_nodes.py
+++ b/tests/test_util_nodes.py
@@ -87,7 +87,6 @@ def test_extract_messages():
nodes.rubric, 1,
)
-
text = dedent(
"""
| spam
@@ -100,7 +99,6 @@ def test_extract_messages():
nodes.line, 2,
)
-
text = dedent(
"""
section
@@ -118,7 +116,6 @@ def test_extract_messages():
nodes.line, 2,
)
-
text = dedent(
"""
* | **Title 1**
diff --git a/tests/test_writer_latex.py b/tests/test_writer_latex.py
new file mode 100644
index 000000000..72eb7ed2a
--- /dev/null
+++ b/tests/test_writer_latex.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+"""
+ test_writer_latex
+ ~~~~~~~~~~~~~~~~
+
+ Test the LaTeX writer
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+from __future__ import print_function
+from sphinx.writers.latex import rstdim_to_latexdim
+
+from util import raises
+
+
+def test_rstdim_to_latexdim():
+ # Length units docutils supported
+ # http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#length-units
+ assert rstdim_to_latexdim('160em') == '160em'
+ assert rstdim_to_latexdim('160px') == '160\\sphinxpxdimen'
+ assert rstdim_to_latexdim('160in') == '160in'
+ assert rstdim_to_latexdim('160cm') == '160cm'
+ assert rstdim_to_latexdim('160mm') == '160mm'
+ assert rstdim_to_latexdim('160pt') == '160bp'
+ assert rstdim_to_latexdim('160pc') == '160pc'
+ assert rstdim_to_latexdim('30%') == '0.300\\linewidth'
+ assert rstdim_to_latexdim('160') == '160\\sphinxpxdimen'
+
+ # flaot values
+ assert rstdim_to_latexdim('160.0em') == '160.0em'
+ assert rstdim_to_latexdim('.5em') == '.5em'
+
+ # unknown values (it might be generated by 3rd party extension)
+ raises(ValueError, rstdim_to_latexdim, 'unknown')
+ assert rstdim_to_latexdim('160.0unknown') == '160.0unknown'
diff --git a/tests/typing_test_data.py b/tests/typing_test_data.py
index 74a906ad1..461be7831 100644
--- a/tests/typing_test_data.py
+++ b/tests/typing_test_data.py
@@ -46,3 +46,11 @@ def f7(x: Callable[[int, str], int]) -> None:
def f8(x: Tuple[int, str], y: Tuple[int, ...]) -> None:
pass
+
+
+class CustomAnnotation:
+ def __repr__(self):
+ return 'CustomAnnotation'
+
+def f9(x: CustomAnnotation(), y: 123) -> None:
+ pass
diff --git a/tests/util.py b/tests/util.py
index b3f5e01d9..27b41bc15 100644
--- a/tests/util.py
+++ b/tests/util.py
@@ -26,7 +26,7 @@ from sphinx.theming import Theme
from sphinx.ext.autodoc import AutoDirective
from sphinx.pycode import ModuleAnalyzer
-from path import path, repr_as
+from path import path, repr_as # NOQA
try:
# Python >=3.3
@@ -110,6 +110,7 @@ except ImportError:
def assert_in(x, thing, msg=''):
if x not in thing:
assert False, msg or '%r is not in %r' % (x, thing)
+
def assert_not_in(x, thing, msg=''):
if x in thing:
assert False, msg or '%r is in %r' % (x, thing)
@@ -308,3 +309,7 @@ def find_files(root, suffix=None):
for f in [f for f in files if not suffix or f.endswith(suffix)]:
fpath = dirpath / f
yield os.path.relpath(fpath, root)
+
+
+def strip_escseq(text):
+ return re.sub('\x1b.*?m', '', text)
diff --git a/tox.ini b/tox.ini
index 8fcb7b177..b646fd285 100644
--- a/tox.ini
+++ b/tox.ini
@@ -6,6 +6,7 @@ deps=
nose
sqlalchemy
whoosh
+ html5lib
setenv =
SPHINX_TEST_TEMPDIR = {envdir}/testbuild
commands=
diff --git a/utils/check_sources.py b/utils/check_sources.py
index 16bc918cb..18d444057 100755
--- a/utils/check_sources.py
+++ b/utils/check_sources.py
@@ -223,11 +223,8 @@ def main(argv):
print("Checking %s..." % fn)
try:
- f = open(fn, 'rb')
- try:
+ with open(fn, 'rb') as f:
lines = list(f)
- finally:
- f.close()
except (IOError, OSError) as err:
print("%s: cannot open: %s" % (fn, err))
num += 1
diff --git a/utils/reindent.py b/utils/reindent.py
index ef53fe8ca..ee13a634a 100755
--- a/utils/reindent.py
+++ b/utils/reindent.py
@@ -40,11 +40,13 @@ you'd prefer. You can always use the --nobackup option to prevent this.
"""
from __future__ import print_function
-__version__ = "1"
-
-import tokenize
-import os, shutil
+import os
import sys
+import shutil
+import tokenize
+from six.ranges import range
+
+__version__ = "1"
if sys.version_info >= (3, 0):
def tokens(readline, tokeneater):
@@ -58,11 +60,13 @@ recurse = 0
dryrun = 0
makebackup = True
+
def usage(msg=None):
if msg is not None:
print(msg, file=sys.stderr)
print(__doc__, file=sys.stderr)
+
def errprint(*args):
sep = ""
for arg in args:
@@ -70,12 +74,13 @@ def errprint(*args):
sep = " "
sys.stderr.write("\n")
+
def main():
import getopt
global verbose, recurse, dryrun, makebackup
try:
opts, args = getopt.getopt(sys.argv[1:], "drnvh",
- ["dryrun", "recurse", "nobackup", "verbose", "help"])
+ ["dryrun", "recurse", "nobackup", "verbose", "help"])
except getopt.error as msg:
usage(msg)
return
@@ -99,6 +104,7 @@ def main():
for arg in args:
check(arg)
+
def check(file):
if os.path.isdir(file) and not os.path.islink(file):
if verbose:
@@ -108,8 +114,8 @@ def check(file):
fullname = os.path.join(file, name)
if ((recurse and os.path.isdir(fullname) and
not os.path.islink(fullname) and
- not os.path.split(fullname)[1].startswith("."))
- or name.lower().endswith(".py")):
+ not os.path.split(fullname)[1].startswith(".")) or
+ name.lower().endswith(".py")):
check(fullname)
return
@@ -121,8 +127,8 @@ def check(file):
errprint("%s: I/O Error: %s" % (file, str(msg)))
return
- r = Reindenter(f)
- f.close()
+ with f:
+ r = Reindenter(f)
if r.run():
if verbose:
print("changed.")
@@ -134,9 +140,8 @@ def check(file):
shutil.copyfile(file, bak)
if verbose:
print("backed up", file, "to", bak)
- f = open(file, "w")
- r.write(f)
- f.close()
+ with open(file, "w") as f:
+ r.write(f)
if verbose:
print("wrote new", file)
return True
@@ -145,6 +150,7 @@ def check(file):
print("unchanged.")
return False
+
def _rstrip(line, JUNK='\n \t'):
"""Return line stripped of trailing spaces, tabs, newlines.
@@ -158,8 +164,8 @@ def _rstrip(line, JUNK='\n \t'):
i -= 1
return line[:i]
-class Reindenter:
+class Reindenter:
def __init__(self, f):
self.find_stmt = 1 # next token begins a fresh stmt?
self.level = 0 # current indent level
@@ -212,21 +218,21 @@ class Reindenter:
want = have2want.get(have, -1)
if want < 0:
# Then it probably belongs to the next real stmt.
- for j in xrange(i+1, len(stats)-1):
+ for j in range(i+1, len(stats)-1):
jline, jlevel = stats[j]
if jlevel >= 0:
if have == getlspace(lines[jline]):
want = jlevel * 4
break
- if want < 0: # Maybe it's a hanging
- # comment like this one,
+ if want < 0: # Maybe it's a hanging
+ # comment like this one,
# in which case we should shift it like its base
# line got shifted.
- for j in xrange(i-1, -1, -1):
+ for j in range(i-1, -1, -1):
jline, jlevel = stats[j]
if jlevel >= 0:
- want = have + getlspace(after[jline-1]) - \
- getlspace(lines[jline])
+ want = (have + getlspace(after[jline-1]) -
+ getlspace(lines[jline]))
break
if want < 0:
# Still no luck -- leave it alone.
@@ -301,6 +307,7 @@ class Reindenter:
if line: # not endmarker
self.stats.append((position[0], self.level))
+
# Count number of leading blanks.
def getlspace(line):
i, n = 0, len(line)
diff --git a/utils/release-checklist b/utils/release-checklist
index ff290471b..3dd52158c 100644
--- a/utils/release-checklist
+++ b/utils/release-checklist
@@ -1,20 +1,26 @@
Release checklist
=================
+* Open https://travis-ci.org/sphinx-doc/sphinx/branches and check stable branch is green
* Check `git status`
* Run `make style-check`
* Run `tx pull -a -f` in sphinx/locale if final major release
* Update version info in sphinx/__init__.py
* Update release date in CHANGES
-* `git commit`
+* `git commit -am 'Bump to x.y.z final'`
* `make clean`
-* `python setup.py release bdist_wheel sdist upload`
+* `python setup.py release bdist_wheel sdist upload --identity=[your key]`
* Check PyPI release page for obvious errors
* `git tag` with version number
* Merge default into stable if final major release
-* Update homepage (release info), regenerate docs (+printable!)
+* `git push origin stable --tags`
+* Open https://readthedocs.org/dashboard/sphinx/versions/ and enable the released version
* Add new version/milestone to tracker categories
-* Write announcement and send to mailing list/python-announce
+* Write announcement and send to sphinx-dev, sphinx-users and python-announce
* Update version info, add new CHANGES entry for next version
-* `git commit`
-* `git push`
+* `git commit -am 'Bump version'`
+* `git push origin stable`
+* `git checkout master`
+* `git merge stable`
+* `git push origin master`
+* Update `sphinx-doc-translations <https://github.com/sphinx-doc/sphinx-doc-translations>`_